Curious interaction between trap and sleep

Hi,

Can someone explain why this code:


fork do
puts(“Child’s PID: #{Process.pid}”)
end

trap(:SIGCHLD) do
$pid = Process.wait
end

puts(“Parent’s PID: #{Process.pid}”)
puts(“My son is no more a zombie (check with ps)…”)

sleep(20)

if $?.exitstatus == 0
puts("#{$pid} died gracefully")
else
puts("#{$pid} doesn’t die gracefully")
end
exit(0)

doesn’t work as i expect (it seems the sleep is never called: the
parent process exit immediately after it get SIGCHLD…).

The same script, with the trap commented out work ok (the child
process is a zombie during 20 sec).

And, yes, i know about Process.detach but that’s a try to mimic a C
idiom.

The sleep is called when I run it. What are you trying to achieve?

“Timothy G.” [email protected] writes:

The sleep is called when I run it. What are you trying to achieve?

I expect the parent process sleep during 20 sec… That’s not the case:
it exits as soon as it receives SIGCHLD. Did you try to run my script?

If seems that this sleep is interrupted by the SIGCHLD signal, hence
my surprise. Alone, sleep works well.

Hi,

In message “Re: Curious interaction between trap and sleep”
on Thu, 16 Feb 2006 07:28:27 +0900, Eric J. [email protected]
writes:

|Can someone explain why this code:

|doesn’t work as i expect (it seems the sleep is never called: the
|parent process exit immediately after it get SIGCHLD…).

It does work on my machine (1.8.4 2006-02-15; i686-linux), although I
have to move trap before fork. Do you mind if I ask you more
information about the version of your Ruby, and your platform?

						matz.

Yukihiro M. [email protected] writes:

It does work on my machine (1.8.4 2006-02-15; i686-linux), although I
have to move trap before fork. Do you mind if I ask you more
information about the version of your Ruby, and your platform?

In fact, i realize now it’s may be a “no-problem”: i was thinking that
sleep(3) was not affected by a signal like SIGCHLD so i didn’t
understood why catching this signal make sleep stop working. Now, i
know that sleep is affected by any signal not discarded, so i know why
my
script doesn’t work as I expected :slight_smile:

My confusion comes from a C program i’ve written, equivalent to the
Ruby script: in this C program, the sleep(20) call was sleeping 20 sec
in the parent process, despite a sigaction on SIGCHILD: that was not
the case with my Ruby script, where the sleep function in the parent
process stopped working as soon as the child died, hence my trouble.

Actually, i realize now that it was only a question of timing: in the
C program, SIGCHLD was caught before the parent process call
sleep(20): so this sleep was not interrupted. In the Ruby script, a
different timing makes the sleep starting before the child
die… (anyway, that’s the conclusion i’ve reached so far…).

I’ve tried this script with 1.8.4 both on OS-X (DP ports) and FreeBSD
5.2 and 6.0, with or without pthreads. I’ve also tried to code the
same thing with Python and Perl (with POSIX module) : both languages
produce the same behaviour than Ruby… so i definitively think the
problem came from my misunderstanding of this timing problem.

Hi,

In message “Re: Curious interaction between trap and sleep”
on Fri, 17 Feb 2006 08:58:29 +0900, Eric J. [email protected]
writes:

|Actually, i realize now that it was only a question of timing: in the
|C program, SIGCHLD was caught before the parent process call
|sleep(20): so this sleep was not interrupted. In the Ruby script, a
|different timing makes the sleep starting before the child
|die… (anyway, that’s the conclusion i’ve reached so far…).

This is a intended behavior for C program (sleep(3)) but not for Ruby
program, hence it doesn’t use sleep(3) and Ruby’s sleep method should
always sleep for specified duration. So I consider this as a bug in
Ruby, and it will be fixed in the next release. Thank you.

For a work around, put “Thread.start{sleep}” at the head of your
program, #sleep would sleep for specified time amount.

						matz.