From 22b1a91c2a07e6d6a57975a1ab47d66f92aa21f2 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Fri, 3 Jun 2022 19:32:56 +0900 Subject: 50306: fix wait for child that was stopped/continued do not call addbgstatus() when child is stopped/continued --- ChangeLog | 5 +++++ Src/jobs.c | 20 ++++++++++++++++++-- Src/signals.c | 10 ++++------ Test/A05execution.ztst | 7 +++++++ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 43a805bc7..780f967f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-06-03 Jun-ichi Takimoto + + * 50306: Src/jobs.c, Src/signals.c, Test/A05execution.ztst: fix + wait builtin for child that has been stopped and continued. + 2022-05-30 Bart Schaefer * Marlon Richert: 50307 (cf. PWS 50205): diff --git a/Src/jobs.c b/Src/jobs.c index a91ef787f..aa32f4e80 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -414,7 +414,7 @@ storepipestats(Job jn, int inforeground, int fixlastval) jpipestats[i] = (WIFSIGNALED(p->status) ? 0200 | WTERMSIG(p->status) : (WIFSTOPPED(p->status) ? - 0200 | WEXITSTATUS(p->status) : + 0200 | WSTOPSIG(p->status) : WEXITSTATUS(p->status))); if (jpipestats[i]) pipefail = jpipestats[i]; @@ -471,7 +471,7 @@ update_job(Job jn) val = (WIFSIGNALED(pn->status) ? 0200 | WTERMSIG(pn->status) : (WIFSTOPPED(pn->status) ? - 0200 | WEXITSTATUS(pn->status) : + 0200 | WSTOPSIG(pn->status) : WEXITSTATUS(pn->status))); signalled = WIFSIGNALED(pn->status); } @@ -2221,6 +2221,7 @@ addbgstatus(pid_t pid, int status) { static long child_max; Bgstatus bgstatus_entry; + LinkNode node; if (!child_max) { #ifdef _SC_CHILD_MAX @@ -2244,6 +2245,21 @@ addbgstatus(pid_t pid, int status) if (!bgstatus_list) return; } +#ifdef DEBUG + /* See if an entry already exists for the pid */ + for (node = firstnode(bgstatus_list); node; incnode(node)) { + bgstatus_entry = (Bgstatus)getdata(node); + if (bgstatus_entry->pid == pid) { + /* In theory this should not happen because addbgstatus() is + * called only once when the process exits or gets killed. */ + dputs("addbgstatus called again: pid %d: status %d -> %d", + pid, bgstatus_entry->status, status); + bgstatus_entry->status = status; + return; + } + } +#endif + /* Add an entry for the pid */ if (bgstatus_count == child_max) { /* Overflow. List is in order, remove first */ rembgstatus(firstnode(bgstatus_list)); diff --git a/Src/signals.c b/Src/signals.c index 5c787e2a8..a61368554 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -576,12 +576,10 @@ wait_for_processes(void) */ if (jn && !(jn->stat & (STAT_CURSH|STAT_BUILTIN)) && jn - jobtab != thisjob) { - int val = (WIFSIGNALED(status) ? - 0200 | WTERMSIG(status) : - (WIFSTOPPED(status) ? - 0200 | WEXITSTATUS(status) : - WEXITSTATUS(status))); - addbgstatus(pid, val); + if (WIFEXITED(status)) + addbgstatus(pid, WEXITSTATUS(status)); + else if (WIFSIGNALED(status)) + addbgstatus(pid, 0200 | WTERMSIG(status)); } unqueue_signals(); diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst index d95ee363c..b257ddf2c 100644 --- a/Test/A05execution.ztst +++ b/Test/A05execution.ztst @@ -396,6 +396,13 @@ F:anonymous function, and a descriptor leak when backgrounding a pipeline # TBD: the 0 above is believed to be bogus and should also be turned # into 127 when the ccorresponding bug is fixed in the main shell. + sleep 1 & pid=$! + kill -STOP $pid + sleep 1 + kill -CONT $pid + wait $pid +0:wait for stopped and continued process + # Without the outer subshell, the test harness reports the pre-46060 behaviour # as "skipped" rather than "failed". (( exit 130 ) | { sleep 1; echo hello }) -- cgit 1.4.1