Bug #16835
closedSIGCHLD + system new behavior on 2.6
Description
In rubies < 2.5, the system
command did not trigger sigchld signal traps. On ruby >= 2.6 it does. This appears to have been introduced by https://github.com/ruby/ruby/commit/054a412d540e7ed2de63d68da753f585ea6616c3 . To observe the change in behavior, run the following code on ruby 2.5 and 2.6:
Signal.trap("CLD") { puts "Child died" }; system("true")
On ruby 2.5 it won't print anything. On ruby 2.6 it will print "Child died". I believe this is an unintended, undocumented change in behavior, but I may be wrong about that.
Updated by maths22 (Jacob Burroughs) over 4 years ago
- Subject changed from SIGCHLD + system to SIGCHLD + system new behavior on 2.6
Updated by jeremyevans0 (Jeremy Evans) over 4 years ago
I agree that based on a review of the commit message, this change was unintended, and since the issue was not known previously, it was not documented.
However, I think the new behavior makes more sense. system
creates a child process, so when the child process exits, it should trigger a SIGCLD
trap. That is how sh
itself works (example assumes echo
is a shell built-in, and uses CHLD instead of CLD as that is the signal name on the operating system I am using):
trap "echo child exit" CHLD
$ echo 1
1
$ /bin/echo 1
1
child exit
Other than compatibility with Ruby 2.5 and prior, is there a good reason to follow the historical behavior?
Updated by maths22 (Jacob Burroughs) over 4 years ago
jeremyevans0 (Jeremy Evans) wrote in #note-2:
I agree that based on a review of the commit message, this change was unintended, and since the issue was not known previously, it was not documented.
However, I think the new behavior makes more sense.
system
creates a child process, so when the child process exits, it should trigger aSIGCLD
trap. That is howsh
itself works (example assumesecho
is a shell built-in, and uses CHLD instead of CLD as that is the signal name on the operating system I am using):trap "echo child exit" CHLD $ echo 1 1 $ /bin/echo 1 1 child exit
Other than compatibility with Ruby 2.5 and prior, is there a good reason to follow the historical behavior?
Going by https://github.com/ruby/ruby/commit/6b87ac68dba3d8967d76233766a174c8a82813e3 , it seems like it was a deliberate decision in the past to not have the SIGCLD signal bubble up. I only found this because it caused a rather hard to track down bug in our code, I don't think we actually intended to rely on this behavior.
Updated by maths22 (Jacob Burroughs) over 4 years ago
Also I have tested and the old behavior (not calling the CLD signal handler) does appear to match the glibc behavior
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void proc_exit()
{
printf ("Handler\n");
}
int main ()
{
signal(SIGCHLD, proc_exit);
system("true");
sleep(1);
}
Updated by jeremyevans0 (Jeremy Evans) over 4 years ago
If I compile that program on OpenBSD, it outputs Handler
. So system(3) behavior appears to be operating-system (or libc) specific.
Updated by maths22 (Jacob Burroughs) over 4 years ago
Oh that's definitely interesting. Both on my mac and on a freebsd server I spot-checked on it outputs nothing. But evidently there isn't a settled "correct" answer for how this should behave.
Updated by mame (Yusuke Endoh) over 3 years ago
- Status changed from Open to Rejected
We discussed this ticket at today's dev-meeting. We agreed that we should change nothing for this.
Indeed it looked an unintentional change, but it is too late to revert the behavior because Ruby 2.6 was released three years ago and is already under the security maintenance phase. Also, it is not trivial whether SIGCHILD should be blocked or signaled.