Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-60253

bash calls SIGCHLD traps even when "monitor" is off (the default)

    • Icon: Bug Bug
    • Resolution: Not a Bug
    • Icon: Undefined Undefined
    • None
    • rhel-9.4, rhel-10.0.beta
    • bash
    • None
    • Yes
    • Important
    • rhel-sst-cs-plumbers
    • ssg_core_services
    • 2
    • False
    • Hide

      None

      Show
      None
    • None
    • Red Hat Enterprise Linux
    • None
    • None
    • None
    • All
    • None

      What were you trying to do that didn't work?

      With default settings, the monitor option is off. In such case, traps on CHLD signal should not be called, as it has ever been on RHEL7 and RHEL8.
      Unfortunately there is a bug in RHEL9 bash but also Upstream bash which leads to calling CHLD traps whatever the "monitor" mode is, as shown in the example below (courtesy of customer finding this):

      #!/bin/bash
      
      function trap_handler {
      	echo "trap_handler called"
      }
      
      trap trap_handler CHLD
      
      echo "${SHELLOPTS}"
      /bin/date
      

      Execution on RHEL7, RHEL8 (correct):

      $ ./trap_sigchld.sh 
      braceexpand:hashall:interactive-comments
      Thu Sep 26 11:23:24 CEST 2024
      

      Execution on RHEL9 and Fedora 40 (incorrect):

      braceexpand:hashall:interactive-comments
      Thu Sep 26 11:25:59 AM CEST 2024
      trap_handler called
      

      What is the impact of this issue to you?

      Breaks custom scripts setting CHLD handler but not activating it all the time.

      Please provide the package NVR for which the bug is seen:

      bash-5.1.8-9.el9.x86_64
      bash-5.2.26-3.fc40.x86_64

      How reproducible is this bug?:

      Always see above.

      Root Cause Analysis

      It appears that the code dealing with SIGCHLD signal handling is missing a condition on job_control in RHEL9 and Upstream code:

      RHEL8 (bash-4.4/jobs.c) - line 3645

      3644   /* Call a SIGCHLD trap handler for each child that exits, if one is set. */
      3645   if (job_control && children_exited &&
      3646       (signal_is_trapped (SIGCHLD) || trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER) &&
      3647       trap_list[SIGCHLD] != (char *)IGNORE_SIG)
      3648     {
      

      RHEL9 (bash-5.1/jobs.c) - line 3942

      3941   /* Call a SIGCHLD trap handler for each child that exits, if one is set. */
      3942   if (children_exited &&
      3943       (signal_is_trapped (SIGCHLD) || trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER) &&
      3944       trap_list[SIGCHLD] != (char *)IGNORE_SIG)
      3945     {
      

      This removal of the condition on job_control initially showed up Upstream in commit below, created 5 years ago:

      commit d233b485e83c3a784b803fb894280773f16f2deb (tag: bash-5.0)
      Author: Chet Ramey <chet.ramey@case.edu>
      Date:   Mon Jan 7 09:27:52 2019 -0500
      
          bash-5.0 distribution sources and documentation
      ---
       jobs.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
       1 file changed, 179 insertions(+), 73 deletions(-)
      
      diff --git a/jobs.c b/jobs.c
      index 5ee21e10..ce2bdf24 100644
      --- a/jobs.c
      +++ b/jobs.c
      
      [...]
         /* Call a SIGCHLD trap handler for each child that exits, if one is set. */
      -  if (job_control && children_exited &&
      +  if (children_exited &&
             (signal_is_trapped (SIGCHLD) || trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER) &&
             trap_list[SIGCHLD] != (char *)IGNORE_SIG)
           {
      

      IMHO it's due to a bad merge.

              rhn-support-svashish Siteshwar Vashisht
              rhn-support-rmetrich Renaud Métrich
              Siteshwar Vashisht Siteshwar Vashisht
              Karel Volný Karel Volný
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: