aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-08-04 02:20:19 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-08-04 02:20:19 +0200
commitcf792a58abc4fc55d0622333d0eb17c6a80dc497 (patch)
treebd740050c3ac79b0db76bd29728dd4d29120ccc6 /shell
parent0a53eadea528673a813c5f9312b1f53130429f7c (diff)
downloadbusybox-w32-cf792a58abc4fc55d0622333d0eb17c6a80dc497.tar.gz
busybox-w32-cf792a58abc4fc55d0622333d0eb17c6a80dc497.tar.bz2
busybox-w32-cf792a58abc4fc55d0622333d0eb17c6a80dc497.zip
NOFORK fixes
"rm -i FILE" and "yes" can now be interrupted by ^C in hush. This also now works: $ usleep 19999999 ^C $ echo $? 130 function old new delta run_pipe 1668 1711 +43 pseudo_exec_argv 312 321 +9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 52/0) Total: 52 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 7cceab30d..2e435cf9f 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -7063,6 +7063,8 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
7063 if (APPLET_IS_NOEXEC(a)) { 7063 if (APPLET_IS_NOEXEC(a)) {
7064 /* Do not leak open fds from opened script files etc */ 7064 /* Do not leak open fds from opened script files etc */
7065 close_all_FILE_list(); 7065 close_all_FILE_list();
7066 /* Without this, "rm -i FILE" can't be ^C'ed: */
7067 switch_off_special_sigs(G.special_sig_mask);
7066 debug_printf_exec("running applet '%s'\n", argv[0]); 7068 debug_printf_exec("running applet '%s'\n", argv[0]);
7067 run_applet_no_and_exit(a, argv[0], argv); 7069 run_applet_no_and_exit(a, argv[0], argv);
7068 } 7070 }
@@ -7725,6 +7727,24 @@ static NOINLINE int run_pipe(struct pipe *pi)
7725 add_vars(old_vars); 7727 add_vars(old_vars);
7726/* clean_up_and_ret0: */ 7728/* clean_up_and_ret0: */
7727 restore_redirects(squirrel); 7729 restore_redirects(squirrel);
7730 /*
7731 * Try "usleep 99999999" + ^C + "echo $?"
7732 * with FEATURE_SH_NOFORK=y.
7733 */
7734 if (!funcp) {
7735 /* It was builtin or nofork.
7736 * if this would be a real fork/execed program,
7737 * it should have died if a fatal sig was received.
7738 * But OTOH, there was no separate process,
7739 * the sig was sent to _shell_, not to non-existing
7740 * child.
7741 * Let's just handle ^C only, this one is obvious:
7742 * we aren't ok with exitcode 0 when ^C was pressed
7743 * during builtin/nofork.
7744 */
7745 if (sigismember(&G.pending_set, SIGINT))
7746 rcode = 128 + SIGINT;
7747 }
7728 clean_up_and_ret1: 7748 clean_up_and_ret1:
7729 free(argv_expanded); 7749 free(argv_expanded);
7730 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) 7750 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
@@ -7740,6 +7760,14 @@ static NOINLINE int run_pipe(struct pipe *pi)
7740 if (rcode == 0) { 7760 if (rcode == 0) {
7741 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", 7761 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
7742 argv_expanded[0], argv_expanded[1]); 7762 argv_expanded[0], argv_expanded[1]);
7763 /*
7764 * Note: signals (^C) can't interrupt here.
7765 * We remember them and they will be acted upon
7766 * after applet returns.
7767 * This makes applets which can run for a long time
7768 * and/or wait for user input ineligible for NOFORK:
7769 * for example, "yes" or "rm" (rm -i waits for input).
7770 */
7743 rcode = run_nofork_applet(n, argv_expanded); 7771 rcode = run_nofork_applet(n, argv_expanded);
7744 } 7772 }
7745 goto clean_up_and_ret; 7773 goto clean_up_and_ret;
@@ -8160,7 +8188,7 @@ static int run_list(struct pipe *pi)
8160 /* Last command's pid goes to $! */ 8188 /* Last command's pid goes to $! */
8161 G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid; 8189 G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
8162 debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n"); 8190 debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
8163/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash says 0 */ 8191/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash say 0 */
8164 rcode = EXIT_SUCCESS; 8192 rcode = EXIT_SUCCESS;
8165 goto check_traps; 8193 goto check_traps;
8166 } else { 8194 } else {
@@ -9791,6 +9819,7 @@ static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid
9791 /* So, did we get a signal? */ 9819 /* So, did we get a signal? */
9792 sig = check_and_run_traps(); 9820 sig = check_and_run_traps();
9793 if (sig /*&& sig != SIGCHLD - always true */) { 9821 if (sig /*&& sig != SIGCHLD - always true */) {
9822 /* Do this for any (non-ignored) signal, not only for ^C */
9794 ret = 128 + sig; 9823 ret = 128 + sig;
9795 break; 9824 break;
9796 } 9825 }