-
Bug
-
Resolution: Not a Bug
-
Undefined
-
None
-
rhel-9.4, rhel-10.0.beta
-
None
-
Yes
-
Important
-
rhel-sst-cs-plumbers
-
ssg_core_services
-
2
-
False
-
-
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.