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>
This commit is contained in:
Denys Vlasenko 2016-10-28 22:39:12 +02:00
parent 7e6753609d
commit 9db74e49e5

View File

@ -9529,13 +9529,22 @@ static int FAST_FUNC builtin_wait(char **argv)
if (errno || pid <= 0) { if (errno || pid <= 0) {
/* mimic bash message */ /* mimic bash message */
bb_error_msg("wait: '%s': not a pid or valid job spec", *argv); 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? */ /* Do we have such child? */
ret = waitpid(pid, &status, WNOHANG); ret = waitpid(pid, &status, WNOHANG);
if (ret < 0) { if (ret < 0) {
/* No */ /* No */
if (errno == ECHILD) { 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 */ /* Example: "wait 1". mimic bash message */
bb_error_msg("wait: pid %d is not a child of this shell", (int)pid); bb_error_msg("wait: pid %d is not a child of this shell", (int)pid);
} else { } else {
@ -9543,7 +9552,9 @@ static int FAST_FUNC builtin_wait(char **argv)
bb_perror_msg("wait %s", *argv); bb_perror_msg("wait %s", *argv);
} }
ret = 127; ret = 127;
} else if (ret == 0) { continue; /* bash checks all argv[] */
}
if (ret == 0) {
/* Yes, and it still runs */ /* Yes, and it still runs */
ret = wait_for_child_or_signal(pid); ret = wait_for_child_or_signal(pid);
} else { } else {
@ -9553,8 +9564,7 @@ static int FAST_FUNC builtin_wait(char **argv)
if (WIFSIGNALED(status)) if (WIFSIGNALED(status))
ret = 128 + WTERMSIG(status); ret = 128 + WTERMSIG(status);
} }
argv++; } while (*++argv);
} while (*argv);
return ret; return ret;
} }