From: Caleb Clausen Date: 2010-10-04T11:29:29+09:00 Subject: Re: having problems with open4 and stuck forked processes On 10/3/10, Tim Uckun wrote: > Hey guys I want to revist this issue because I can't seem to find any > documentation on how to do this. > > What I want to do seem simple enough. I want to shell out to a process > which sometimes gets stuck. It won't return at all. It just sits there > taking up 100% of the CPU (one of the cores anyway). I just want to > make sure that if the process does not end in a reasonable amount of > time I want to kill it. > > So far I have tried wrapping it in a timeout block but that doesn't > always trigger for some reason. I have plenty of error handling and > have an ensure block which says to kill the process if it exists but > nothing I do seems to work. Sooner or later I get a stuck process that > hangs around forever till I kill it by hand. Timeout::timeout is kind of a hack. It's probably better to avoid it. > Surely there is a simple way to do this. > > Here is the code I have so far. > > http://gist.github.com/609119 Your problem may be that you're sending signal 0; you should pass "TERM" or (if that won't work) "KILL" as the first parameter to Signal.kill. signal 0 just queries if the process can receive signals or not... If you want to use select instead of timeout, then instead of this: Timeout::timeout(seconds) { @pid, @stdin, @stdout, @stderr = Open4.popen4(cmd) ignored, @status = Process::waitpid2 @pid if @status.exitstatus != 0 raise "Exit Status not zero" end } You should use something like this: (UNTESTED) @pid, @stdin, @stdout, @stderr = Open4.popen4(cmd) if IO::select([@stdout],nil,nil,seconds) Util.kill_process_if_exists? @pid else fail 'unexpected data on stdout' end ignored, @status = Process::waitpid2 @pid if @status.exitstatus != 0 raise "Exit Status not zero" end Except, if the external process actually prints something to stdout, then you need to call select in a loop until select returns nil, with decreasing timeouts depending on how much time has passed. Unfortunately, 'ri Kernel#select' seems to be broken... it just refers you back to Kernel#select. I hope somebody fixes that. Check what it says in the pickaxe instead. (There's a free version available online if you don't own a copy yourself.)