Question

I am experimenting with multiple processes. I am trapping SIGCLD to execute something when the child is done. It is working on IRB but not when I execute as a ruby script.

pid = fork {sleep 2; puts 'hello'}
trap('CLD') { puts "pid: #{pid} exited with code"}

When I run the above from IRB, I both lines are printed but when I run it as a ruby script, the line within the trap procedure does not show up.

Était-ce utile?

La solution

IRB gives you an outer loop, which means that the ruby process doesn't exit until you decide to kill it. The problem with your ruby script is that the main process is finishing and killing your child (yikes) before it has the chance to trap the signal.

My guess is that this is a test script, and the chances are that your desired program won't have the case where the parent finishes before the child. To see your trap working in a plain ruby script, add a sleep at the end:

pid = fork {sleep 2; puts 'hello'}
trap('CLD') { puts "pid: #{pid} exited with code"}
sleep 3

To populate the $? global variable, you should explicitly wait for the child process to exit:

pid = fork {sleep 2; puts 'hello'}
trap('CLD') { puts "pid: #{pid} exited with code #{$? >> 8}" }
Process.wait

If you do want the child to run after the parent process has died, you want a daemon (double fork).

Autres conseils

When you run your code in IRB, the main thread belongs to IRB so that all the stuff you’ve called is living within virtually infinite time loop.

In a case of script execution, the main thread is your own and it dies before trapping. Try this:

pid = fork {sleep 2; puts 'hello'}
trap('CLD') { puts "pid: #{pid} exited with code"}
sleep 5 # this is needed to prevent main thread to die ASAP

Hope it helps.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top