Project

General

Profile

Actions

Bug #16835

closed

SIGCHLD + system new behavior on 2.6

Added by maths22 (Jacob Burroughs) about 1 year ago. Updated about 1 month ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
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.

Actions #1

Updated by maths22 (Jacob Burroughs) about 1 year ago

  • Subject changed from SIGCHLD + system to SIGCHLD + system new behavior on 2.6

Updated by jeremyevans0 (Jeremy Evans) about 1 year 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) about 1 year 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 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.

Updated by maths22 (Jacob Burroughs) about 1 year 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) about 1 year 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) about 1 year 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) about 1 month 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.

Actions

Also available in: Atom PDF