diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-03-27 18:34:10 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-03-27 18:35:19 +0100 |
commit | e6f51ac6975963e538a28fe2060dd4511143449b (patch) | |
tree | 48b6e06e1f0a23f3b5cb1ff8db0e8b313b5b27f0 /shell | |
parent | 966f087ab41e555fb40a158e7feae7603b31d450 (diff) |
hush: fix "wait -n" to wait for a _job_, not a _process_
function old new delta
checkjobs 163 183 +20
process_wait_result 449 463 +14
leave_var_nest_level 98 107 +9
enter_var_nest_level 32 38 +6
set_vars_and_save_old 147 150 +3
builtin_local 53 56 +3
builtin_wait 322 323 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 7/0 up/down: 56/0) Total: 56 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/shell/hush.c b/shell/hush.c index 7c907686e..fa9afa38e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -923,7 +923,7 @@ struct globals { # define G_flag_return_in_progress 0 #endif smallint exiting; /* used to prevent EXIT trap recursion */ - /* These support $?, $#, and $1 */ + /* These support $? */ smalluint last_exitcode; smalluint expand_exitcode; smalluint last_bg_pid_exitcode; @@ -934,6 +934,9 @@ struct globals { #else # define G_global_args_malloced 0 #endif +#if ENABLE_HUSH_BASH_COMPAT + int dead_job_exitcode; /* for "wait -n" */ +#endif /* how many non-NULL argv's we have. NB: $# + 1 */ int global_argc; char **global_argv; @@ -8657,6 +8660,9 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status) pi->cmds[i].pid = 0; pi->alive_cmds--; if (!pi->alive_cmds) { +#if ENABLE_HUSH_BASH_COMPAT + G.dead_job_exitcode = job_exited_or_stopped(pi); +#endif if (G_interactive_fd) { printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->cmdtext); @@ -8763,11 +8769,7 @@ static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid) /* fg_pipe exited or stopped */ break; } - if (childpid == waitfor_pid /* "wait PID" */ -#if ENABLE_HUSH_BASH_COMPAT - || -1 == waitfor_pid /* "wait -n" (wait for any one child) */ -#endif - ) { + if (childpid == waitfor_pid) { /* "wait PID" */ debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status); rcode = WEXITSTATUS(status); if (WIFSIGNALED(status)) @@ -8778,6 +8780,15 @@ static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid) rcode++; break; /* "wait PID" called us, give it exitcode+1 */ } +#if ENABLE_HUSH_BASH_COMPAT + if (-1 == waitfor_pid /* "wait -n" (wait for any one job) */ + && G.dead_job_exitcode >= 0 /* some job did finish */ + ) { + debug_printf_exec("waitfor_pid:-1\n"); + rcode = G.dead_job_exitcode + 1; + break; + } +#endif /* This wasn't one of our processes, or */ /* fg_pipe still has running processes, do waitpid again */ } /* while (waitpid succeeds)... */ @@ -11510,9 +11521,11 @@ static int FAST_FUNC builtin_wait(char **argv) argv = skip_dash_dash(argv); #if ENABLE_HUSH_BASH_COMPAT - if (argv[0] && !argv[1] && strcmp(argv[0], "-n") == 0) { + if (argv[0] && strcmp(argv[0], "-n") == 0) { /* wait -n */ - return wait_for_child_or_signal(NULL, -1 /*(no job, wait for one child)*/); + /* (bash accepts "wait -n PID" too and ignores PID) */ + G.dead_job_exitcode = -1; + return wait_for_child_or_signal(NULL, -1 /*no job, wait for one job*/); } #endif if (argv[0] == NULL) { @@ -11532,7 +11545,7 @@ static int FAST_FUNC builtin_wait(char **argv) * ^C <-- after ~4 sec from keyboard * $ */ - return wait_for_child_or_signal(NULL, 0 /*(no job and no pid to wait for)*/); + return wait_for_child_or_signal(NULL, 0 /*no job and no pid to wait for*/); } do { |