aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-07 22:56:02 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-07 22:56:02 +0200
commit840a4355d035efc360eeefe5da8a11e47b3c80d3 (patch)
treed68c5ee3d534e241f1585188699ab987c5e01fd2 /shell
parent2db74610cdf8ffb4f9ed99b62c755377d3cc48ea (diff)
downloadbusybox-w32-840a4355d035efc360eeefe5da8a11e47b3c80d3.tar.gz
busybox-w32-840a4355d035efc360eeefe5da8a11e47b3c80d3.tar.bz2
busybox-w32-840a4355d035efc360eeefe5da8a11e47b3c80d3.zip
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>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash_test/ash-misc/wait6.right2
-rwxr-xr-xshell/ash_test/ash-misc/wait6.tests6
-rw-r--r--shell/hush.c15
-rw-r--r--shell/hush_test/hush-misc/wait6.right2
-rwxr-xr-xshell/hush_test/hush-misc/wait6.tests6
5 files changed, 26 insertions, 5 deletions
diff --git a/shell/ash_test/ash-misc/wait6.right b/shell/ash_test/ash-misc/wait6.right
new file mode 100644
index 000000000..12decc137
--- /dev/null
+++ b/shell/ash_test/ash-misc/wait6.right
@@ -0,0 +1,2 @@
10
23
diff --git a/shell/ash_test/ash-misc/wait6.tests b/shell/ash_test/ash-misc/wait6.tests
new file mode 100755
index 000000000..c23713199
--- /dev/null
+++ b/shell/ash_test/ash-misc/wait6.tests
@@ -0,0 +1,6 @@
1# In bash, "wait $!" extracts correct exitcode even if bg task has already exited
2# It prints 0, then 3:
3(sleep 0; exit 3) & sleep 1
4echo $?
5wait $!
6echo $?
diff --git a/shell/hush.c b/shell/hush.c
index 59bddbfff..df96e6fde 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -832,6 +832,7 @@ struct globals {
832 smallint exiting; /* used to prevent EXIT trap recursion */ 832 smallint exiting; /* used to prevent EXIT trap recursion */
833 /* These four support $?, $#, and $1 */ 833 /* These four support $?, $#, and $1 */
834 smalluint last_exitcode; 834 smalluint last_exitcode;
835 smalluint last_bg_pid_exitcode;
835#if ENABLE_HUSH_SET 836#if ENABLE_HUSH_SET
836 /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */ 837 /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
837 smalluint global_args_malloced; 838 smalluint global_args_malloced;
@@ -7387,10 +7388,13 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
7387 found_pi_and_prognum: 7388 found_pi_and_prognum:
7388 if (dead) { 7389 if (dead) {
7389 /* child exited */ 7390 /* child exited */
7390 pi->cmds[i].pid = 0; 7391 int rcode = WEXITSTATUS(status);
7391 pi->cmds[i].cmd_exitcode = WEXITSTATUS(status);
7392 if (WIFSIGNALED(status)) 7392 if (WIFSIGNALED(status))
7393 pi->cmds[i].cmd_exitcode = 128 + WTERMSIG(status); 7393 rcode = 128 + WTERMSIG(status);
7394 pi->cmds[i].cmd_exitcode = rcode;
7395 if (G.last_bg_pid == pi->cmds[i].pid)
7396 G.last_bg_pid_exitcode = rcode;
7397 pi->cmds[i].pid = 0;
7394 pi->alive_cmds--; 7398 pi->alive_cmds--;
7395 if (!pi->alive_cmds) { 7399 if (!pi->alive_cmds) {
7396 if (G_interactive_fd) 7400 if (G_interactive_fd)
@@ -8215,6 +8219,7 @@ static int run_list(struct pipe *pi)
8215#endif 8219#endif
8216 /* Last command's pid goes to $! */ 8220 /* Last command's pid goes to $! */
8217 G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid; 8221 G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
8222 G.last_bg_pid_exitcode = 0;
8218 debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n"); 8223 debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
8219/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash says 0 */ 8224/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash says 0 */
8220 rcode = EXIT_SUCCESS; 8225 rcode = EXIT_SUCCESS;
@@ -9909,6 +9914,7 @@ static int FAST_FUNC builtin_wait(char **argv)
9909 ret = waitpid(pid, &status, WNOHANG); 9914 ret = waitpid(pid, &status, WNOHANG);
9910 if (ret < 0) { 9915 if (ret < 0) {
9911 /* No */ 9916 /* No */
9917 ret = 127;
9912 if (errno == ECHILD) { 9918 if (errno == ECHILD) {
9913 if (G.last_bg_pid > 0 && pid == G.last_bg_pid) { 9919 if (G.last_bg_pid > 0 && pid == G.last_bg_pid) {
9914 /* "wait $!" but last bg task has already exited. Try: 9920 /* "wait $!" but last bg task has already exited. Try:
@@ -9916,7 +9922,7 @@ static int FAST_FUNC builtin_wait(char **argv)
9916 * In bash it prints exitcode 0, then 3. 9922 * In bash it prints exitcode 0, then 3.
9917 * In dash, it is 127. 9923 * In dash, it is 127.
9918 */ 9924 */
9919 /* ret = G.last_bg_pid_exitstatus - FIXME */ 9925 ret = G.last_bg_pid_exitcode;
9920 } else { 9926 } else {
9921 /* Example: "wait 1". mimic bash message */ 9927 /* Example: "wait 1". mimic bash message */
9922 bb_error_msg("wait: pid %d is not a child of this shell", (int)pid); 9928 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)
9925 /* ??? */ 9931 /* ??? */
9926 bb_perror_msg("wait %s", *argv); 9932 bb_perror_msg("wait %s", *argv);
9927 } 9933 }
9928 ret = 127;
9929 continue; /* bash checks all argv[] */ 9934 continue; /* bash checks all argv[] */
9930 } 9935 }
9931 if (ret == 0) { 9936 if (ret == 0) {
diff --git a/shell/hush_test/hush-misc/wait6.right b/shell/hush_test/hush-misc/wait6.right
new file mode 100644
index 000000000..12decc137
--- /dev/null
+++ b/shell/hush_test/hush-misc/wait6.right
@@ -0,0 +1,2 @@
10
23
diff --git a/shell/hush_test/hush-misc/wait6.tests b/shell/hush_test/hush-misc/wait6.tests
new file mode 100755
index 000000000..c23713199
--- /dev/null
+++ b/shell/hush_test/hush-misc/wait6.tests
@@ -0,0 +1,6 @@
1# In bash, "wait $!" extracts correct exitcode even if bg task has already exited
2# It prints 0, then 3:
3(sleep 0; exit 3) & sleep 1
4echo $?
5wait $!
6echo $?