diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-15 23:29:44 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-15 23:29:44 +0000 |
commit | 74a931ac9ea807d14a44baf3fdb957bc58db14c6 (patch) | |
tree | 0d0f7ee4585a7e9bed445236f207a604818f1043 | |
parent | c4ada7934307c6ef0b5b207df13a54fecd4ad81d (diff) | |
download | busybox-74a931ac9ea807d14a44baf3fdb957bc58db14c6.tar.gz |
hush: stop ignoring ^Z in child shells
-rw-r--r-- | shell/hush.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/shell/hush.c b/shell/hush.c index 16f304d81..a5d5741da 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2276,15 +2276,28 @@ void re_execute_shell(char ***to_free, const char *s, char *argv0, char **argv); static void reset_traps_to_defaults(void) { + enum { + JOBSIGS = (1 << SIGTTIN) | (1 << SIGTTOU) | (1 << SIGTSTP) + }; unsigned sig; - int dirty; - if (!G.traps) + if (!G.traps && !(G.non_DFL_mask & JOBSIGS)) return; - dirty = 0; - for (sig = 0; sig < NSIG; sig++) { - if (!G.traps[sig]) + + /* This function is always called in a child shell. + * Child shells are not interactive. + * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling. + * Testcase: (while :; do :; done) + ^Z should background. + */ + G.non_DFL_mask &= ~JOBSIGS; + sigdelset(&G.blocked_set, SIGTTIN); + sigdelset(&G.blocked_set, SIGTTOU); + sigdelset(&G.blocked_set, SIGTSTP); + + if (G.traps) for (sig = 0; sig < NSIG; sig++) { + if (!G.traps[sig]) { continue; + } free(G.traps[sig]); G.traps[sig] = NULL; /* There is no signal for 0 (EXIT) */ @@ -2296,10 +2309,8 @@ static void reset_traps_to_defaults(void) if (sig < 32 && (G.non_DFL_mask & (1 << sig))) continue; sigdelset(&G.blocked_set, sig); - dirty = 1; } - if (dirty) - sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); + sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); } #else /* !BB_MMU */ |