Processes and forks

Hi all, I have a quick problem that I am sure someone here has an
elegant solution for.

I have a ruby script that runs in a loop an external linux process via
gdb:


until checks.empty? do

begin
Timeout::timeout(5) {
system("/usr/bin/gdb --args #{proc} 2>/dev/null")}
rescue Timeout::Error
end

end

What I am trying to do is have gdb terminate after 5 seconds of activity
and move on to debugging the next task. What I am finding however is
that after 5 seconds, my ruby script quits and returns to the command
line and the gdb and debugged processes are left running in the
background.

I can then hit fg and it will start again but this is not what I want; I
want my script to execute gdb and launch it to debug a program, after 5
seconds to terminate debugging and move on to the next binary to debug.

much regards

Subject: Processes and forks
Date: Fri 25 Jan 13 02:04:38AM +0900
Sorry for the delay!

Quoting baq s. ([email protected]):

    Timeout::timeout(5) {

line and the gdb and debugged processes are left running in the
background.

I can then hit fg and it will start again but this is not what I want; I
want my script to execute gdb and launch it to debug a program, after 5
seconds to terminate debugging and move on to the next binary to
debug.

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 believe that gdb has a bit special way to
handle interrupts.

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.

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

You will have to experiment…

Carlo

Subject: Re: Processes and forks
Date: Fri 25 Jan 13 03:55:03AM +0900

Quoting baqtwo front ([email protected]):

many thanks for the detailed reply, much appreciated as you have given
me very useful information to read about and test. All the best to
you.

Glad to have been of help!

Carlo

Hi Carlo,

many thanks for the detailed reply, much appreciated as you have given
me very useful information to read about and test. All the best to you.

On Thu, Jan 24, 2013 at 6:56 PM, Carlo E. Prelz [email protected]
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 ’
from -e:1:in `’

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).

Process::waitpid(pid)
end

That looks like a good solution.

Kind regards

robert