hush: fix "(sleep 1; exit 3) & sleep 2; echo $?; wait $!; echo $?"
function old new delta process_wait_result 414 426 +12 builtin_wait 283 291 +8 run_list 974 978 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 24/0) Total: 24 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
2db74610cd
commit
840a4355d0
2
shell/ash_test/ash-misc/wait6.right
Normal file
2
shell/ash_test/ash-misc/wait6.right
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
0
|
||||||
|
3
|
6
shell/ash_test/ash-misc/wait6.tests
Executable file
6
shell/ash_test/ash-misc/wait6.tests
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
# In bash, "wait $!" extracts correct exitcode even if bg task has already exited
|
||||||
|
# It prints 0, then 3:
|
||||||
|
(sleep 0; exit 3) & sleep 1
|
||||||
|
echo $?
|
||||||
|
wait $!
|
||||||
|
echo $?
|
15
shell/hush.c
15
shell/hush.c
@ -832,6 +832,7 @@ struct globals {
|
|||||||
smallint exiting; /* used to prevent EXIT trap recursion */
|
smallint exiting; /* used to prevent EXIT trap recursion */
|
||||||
/* These four support $?, $#, and $1 */
|
/* These four support $?, $#, and $1 */
|
||||||
smalluint last_exitcode;
|
smalluint last_exitcode;
|
||||||
|
smalluint last_bg_pid_exitcode;
|
||||||
#if ENABLE_HUSH_SET
|
#if ENABLE_HUSH_SET
|
||||||
/* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
|
/* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
|
||||||
smalluint global_args_malloced;
|
smalluint global_args_malloced;
|
||||||
@ -7387,10 +7388,13 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
|
|||||||
found_pi_and_prognum:
|
found_pi_and_prognum:
|
||||||
if (dead) {
|
if (dead) {
|
||||||
/* child exited */
|
/* child exited */
|
||||||
pi->cmds[i].pid = 0;
|
int rcode = WEXITSTATUS(status);
|
||||||
pi->cmds[i].cmd_exitcode = WEXITSTATUS(status);
|
|
||||||
if (WIFSIGNALED(status))
|
if (WIFSIGNALED(status))
|
||||||
pi->cmds[i].cmd_exitcode = 128 + WTERMSIG(status);
|
rcode = 128 + WTERMSIG(status);
|
||||||
|
pi->cmds[i].cmd_exitcode = rcode;
|
||||||
|
if (G.last_bg_pid == pi->cmds[i].pid)
|
||||||
|
G.last_bg_pid_exitcode = rcode;
|
||||||
|
pi->cmds[i].pid = 0;
|
||||||
pi->alive_cmds--;
|
pi->alive_cmds--;
|
||||||
if (!pi->alive_cmds) {
|
if (!pi->alive_cmds) {
|
||||||
if (G_interactive_fd)
|
if (G_interactive_fd)
|
||||||
@ -8215,6 +8219,7 @@ static int run_list(struct pipe *pi)
|
|||||||
#endif
|
#endif
|
||||||
/* Last command's pid goes to $! */
|
/* Last command's pid goes to $! */
|
||||||
G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
|
G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
|
||||||
|
G.last_bg_pid_exitcode = 0;
|
||||||
debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
|
debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
|
||||||
/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash says 0 */
|
/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash says 0 */
|
||||||
rcode = EXIT_SUCCESS;
|
rcode = EXIT_SUCCESS;
|
||||||
@ -9909,6 +9914,7 @@ static int FAST_FUNC builtin_wait(char **argv)
|
|||||||
ret = waitpid(pid, &status, WNOHANG);
|
ret = waitpid(pid, &status, WNOHANG);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* No */
|
/* No */
|
||||||
|
ret = 127;
|
||||||
if (errno == ECHILD) {
|
if (errno == ECHILD) {
|
||||||
if (G.last_bg_pid > 0 && pid == G.last_bg_pid) {
|
if (G.last_bg_pid > 0 && pid == G.last_bg_pid) {
|
||||||
/* "wait $!" but last bg task has already exited. Try:
|
/* "wait $!" but last bg task has already exited. Try:
|
||||||
@ -9916,7 +9922,7 @@ static int FAST_FUNC builtin_wait(char **argv)
|
|||||||
* In bash it prints exitcode 0, then 3.
|
* In bash it prints exitcode 0, then 3.
|
||||||
* In dash, it is 127.
|
* In dash, it is 127.
|
||||||
*/
|
*/
|
||||||
/* ret = G.last_bg_pid_exitstatus - FIXME */
|
ret = G.last_bg_pid_exitcode;
|
||||||
} else {
|
} else {
|
||||||
/* 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);
|
||||||
@ -9925,7 +9931,6 @@ static int FAST_FUNC builtin_wait(char **argv)
|
|||||||
/* ??? */
|
/* ??? */
|
||||||
bb_perror_msg("wait %s", *argv);
|
bb_perror_msg("wait %s", *argv);
|
||||||
}
|
}
|
||||||
ret = 127;
|
|
||||||
continue; /* bash checks all argv[] */
|
continue; /* bash checks all argv[] */
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
2
shell/hush_test/hush-misc/wait6.right
Normal file
2
shell/hush_test/hush-misc/wait6.right
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
0
|
||||||
|
3
|
6
shell/hush_test/hush-misc/wait6.tests
Executable file
6
shell/hush_test/hush-misc/wait6.tests
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
# In bash, "wait $!" extracts correct exitcode even if bg task has already exited
|
||||||
|
# It prints 0, then 3:
|
||||||
|
(sleep 0; exit 3) & sleep 1
|
||||||
|
echo $?
|
||||||
|
wait $!
|
||||||
|
echo $?
|
Loading…
Reference in New Issue
Block a user