On Thu, Jan 24, 2013 at 6:56 PM, Carlo E. Prelz <fluido / fluido.as> wrote:

> The biggest reason why your process does not die is most probably
> because you use system (which starts a shell). The signal reaches the
> shell but not gdb.

I don't think there is a signal at all because system just blocks
until the process dies and the timeout exception is raised *after* the
process has terminated and control comes back into the Ruby
interpreter.  Proof:

Test script:
$ cat k.sh
#!/usr/bin/bash

echo "PID $$"

for i in {0..30}; do
  trap "echo signal $i" $i
done

read -p ENTER # block

Demo to show signal output via pressing Ctrl-C:

$ ./k.sh
PID 2296
ENTERsignal 2
signal 2
signal 2
signal 2

signal 0

Now with Timeout:

$ time ruby -r timeout -e 'Timeout.timeout(2) { system "./k.sh" }'
PID 3552
ENTER
signal 0
-e:1:in `system': execution expired (Timeout::Error)
        from -e:1:in `block in <main>'
        from -e:1:in `<main>'

real    0m18.096s
user    0m0.046s
sys     0m0.201s

As you can see from real time I waited much longer than the timeout of
2 seconds before I pressed enter.

> So, instead of system, you should use Process::spawn. But even then,
> read carefully the doc: if you pass a command line (like in your
> example), you will still have a shell process in the middle. To avoid
> that, you must pass the parts of the command in an array. Every time I
> do this, I have to spend a decent amount of time finding how to
> correctly split the command.

That's generally good advice but I believe in this case not important
for the issue (see above).

> Anyway, you may try with something like:
>
> pid=Process::spawn(array)
>
> begin
>   Timeout::timeout(5) do
>     Process::waitpid(pid)
>   end
> rescue Timeout::Error
>   Process::kill(pid,'KILL')
>   Process::waitpid(pid)
> end

That looks like a good solution.

Kind regards

robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/