Bug #16835
closed
SIGCHLD + system new behavior on 2.6
Added by maths22 (Jacob Burroughs) over 4 years ago.
Updated over 3 years ago.
ruby -v:
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]`
[ruby-core:98156]
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.
- Subject changed from SIGCHLD + system to SIGCHLD + system new behavior on 2.6
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?
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 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?
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.
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);
}
If I compile that program on OpenBSD, it outputs Handler
. So system(3) behavior appears to be operating-system (or libc) specific.
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.
- 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.
Also available in: Atom
PDF
Like0
Like0Like0Like0Like0Like0Like0Like0