Project

General

Profile

Bug #16835

SIGCHLD + system new behavior on 2.6

Added by maths22 (Jacob Burroughs) 7 months ago. Updated 7 months ago.

Status:
Open
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.

#1

Updated by maths22 (Jacob Burroughs) 7 months ago

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

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

Also available in: Atom PDF