diff options
author | Denys Vlasenko | 2016-10-28 22:39:12 +0200 |
---|---|---|
committer | Denys Vlasenko | 2016-10-28 22:39:12 +0200 |
commit | 9db74e49e5b462089c6eec0182d819c0d4708e57 (patch) | |
tree | 79195e02400d0b0bd17f409325db01cf79f03dd6 | |
parent | 7e6753609d102b68a625072fb1660065246a54e2 (diff) | |
download | busybox-9db74e49e5b462089c6eec0182d819c0d4708e57.zip busybox-9db74e49e5b462089c6eec0182d819c0d4708e57.tar.gz |
hush: fix "(sleep 1; exit 3) & sleep 2; echo $?; wait $!; echo $?"
"wait $!" may be just a bit too late: backgrounded $! is gone.
Do not bomb out in this case.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/shell/hush.c b/shell/hush.c index 1f8a3e6..7c2f157 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -9529,13 +9529,22 @@ static int FAST_FUNC builtin_wait(char **argv) if (errno || pid <= 0) { /* mimic bash message */ bb_error_msg("wait: '%s': not a pid or valid job spec", *argv); - return EXIT_FAILURE; + ret = EXIT_FAILURE; + continue; /* bash checks all argv[] */ } /* Do we have such child? */ ret = waitpid(pid, &status, WNOHANG); if (ret < 0) { /* No */ if (errno == ECHILD) { + if (G.last_bg_pid > 0 && pid == G.last_bg_pid) { + /* "wait $!" but last bg task has already exited. Try: + * (sleep 1; exit 3) & sleep 2; echo $?; wait $!; echo $? + * In bash it prints exitcode 0, then 3. + */ + ret = 0; /* FIXME */ + continue; + } /* Example: "wait 1". mimic bash message */ bb_error_msg("wait: pid %d is not a child of this shell", (int)pid); } else { @@ -9543,7 +9552,9 @@ static int FAST_FUNC builtin_wait(char **argv) bb_perror_msg("wait %s", *argv); } ret = 127; - } else if (ret == 0) { + continue; /* bash checks all argv[] */ + } + if (ret == 0) { /* Yes, and it still runs */ ret = wait_for_child_or_signal(pid); } else { @@ -9553,8 +9564,7 @@ static int FAST_FUNC builtin_wait(char **argv) if (WIFSIGNALED(status)) ret = 128 + WTERMSIG(status); } - argv++; - } while (*argv); + } while (*++argv); return ret; } |