how to kill a port's external process?

matthias <>
Fri Jul 27 16:02:10 CEST 2001


 >"Garrett G. Hodgson" wrote:
 >> i'm building a little gui wrapper around a command line audio player.
 >> i've got an erlang process that calls open_port() to spawn the external
 >> player, but it doesn't actually send/receive anything to it over stdio.

The bit which surprised me was that sending a kill to a port started
with open_port({spawn, ...}, [...]) doesn't necessarily kill the unix
process. It merely closes the file file descriptors. This is a problem
when the external process gets stuck in a loop somewhere and thus
stops caring about stdin/stdout. It's surprising because the Erlang book
(9.4) says that the goal is for ports to look just like Erlang
processes from the erlang program's point of view.

I can think of three ways around this. No doubt there are more.

  1. A variant of Per's approach. Wrap the external program so that 
     it reports its pid on startup. That way you can nuke it by 
     using os:cmd("kill .."), or whatever the windows equivalent 
     is. The wrapper could be something like

       #!
       echo "my pid is $$"
       exec $*

     You might then use it as
     
       1> erlang:open_port({spawn, "./wrap.sh sleep 5000"}, []).
       #Port<0.8>
       2> flush().
       Shell got {#Port<0.8>,{data,"my pid is 2097\n"}}
       ok
       3> os:cmd("kill -9 2097").

     It can get more complicated if the child forks.

  2. If you're using heart (or some variant), it may be better to
     report the process IDs to the heart process in some way, for
     instance via a socket.

  3. Hack erlang so that erlang:port_info/2 returns the port's
     unix process ID. I did this but abandoned it in favour of #2
     because it didn't solve the problem of processes left lying
     around if erlang was killed.

Matthias
     



More information about the erlang-questions mailing list