Michal Suchanek
9/9/2008 12:04:00 PM
On 09/09/2008, Mikel Lindsaar <raasdnil@gmail.com> wrote:
> On Sun, Sep 7, 2008 at 12:42 AM, ara.t.howard <ara.t.howard@gmail.com> wrote:
> > On Sep 6, 2008, at 3:43 AM, Mikel Lindsaar wrote:
> >> Hello all,
> >> I am having some (un)fun with timing out a database calls.
>
> > try this:
> > <snip>
>
> > pid = Process.pid
> > signaler = IO.popen "ruby -e'sleep #{ seconds };
> > Process.kill(:TERM.to_s, #{ pid }) rescue nil'"
> > thread = Thread.current
> > handler = Signal.trap('TERM'){ thread.raise Error, seconds.to_s }
> > begin
> > block.call
> > ensure
> > Process.kill 'TERM', signaler.pid rescue nil
> > Signal.trap('TERM', handler)
> > end
>
>
> Ara, thank you _so_ much for this.
>
> I would never have thought of spawning suicidal terminator ruby
> processes to nuke my process :) But works well.
>
> There was a bit of delay (putting out some fires here over the past
> two days) but I got to your code last night and this morning, and it
> basically works... except it doesn't kill off the signaler threads
> fully.
>
> This is because two processes get made, first is the shell which then
> creates the ruby -e "sleep..." blah thread.
>
> The 'hack' I used to solve this is to replace the ensure block with:
>
>
> ensure
> Process.kill 'TERM', signaler.pid rescue nil
>
> Process.kill('TERM', signaler.pid+1) rescue nil
>
> Signal.trap('TERM', handler)
> end
>
>
> But this obviously is insane as it assumes that no other processes get
> started on the computer between sh starting up and it firing off the
> ruby process.
>
> the ps output looks like this:
>
> $ ps -ef | grep ruby
> rails 2153 2152 69 17:04 /usr/sbin/ruby1.8 /usr/bin/rake update:all
> rails 2237 2153 69 17:04 sh -c ruby -e'sleep 40.0;?
> Process.kill(:TERM.to_s, 2153) rescue nil'
> rails 2238 2237 69 17:04 ruby -e'sleep 40.0;?
> Process.kill(:TERM.to_s, 2153) rescue nil'
>
> Any ideas on how to reliably find the PID of the ruby process that the
> sh process created by IO.popen creates?
>
Since you are using popen anyway you can just have your ruby process
print it's PID when it starts, and read it in your terminator.
HTH
Michal