hush: unblock TERM, INT, HUP in child shells too.
This commit is contained in:
parent
f8c1f02d2f
commit
e4bd4f2cc8
73
shell/hush.c
73
shell/hush.c
@ -1022,6 +1022,15 @@ static void free_strings(char **strings)
|
|||||||
* are to count SIGCHLDs [disabled - bug somewhere, + bloat]
|
* are to count SIGCHLDs [disabled - bug somewhere, + bloat]
|
||||||
* and to restore tty pgrp on signal-induced exit.
|
* and to restore tty pgrp on signal-induced exit.
|
||||||
*/
|
*/
|
||||||
|
enum {
|
||||||
|
SPECIAL_INTERACTIVE_SIGS = 0
|
||||||
|
#if ENABLE_HUSH_JOB
|
||||||
|
| (1 << SIGTTIN) | (1 << SIGTTOU) | (1 << SIGTSTP)
|
||||||
|
#endif
|
||||||
|
| (1 << SIGTERM)
|
||||||
|
//TODO | (1 << SIGHUP)
|
||||||
|
| (1 << SIGINT)
|
||||||
|
};
|
||||||
|
|
||||||
//static void SIGCHLD_handler(int sig UNUSED_PARAM)
|
//static void SIGCHLD_handler(int sig UNUSED_PARAM)
|
||||||
//{
|
//{
|
||||||
@ -1059,6 +1068,8 @@ static int check_and_run_traps(int sig)
|
|||||||
// G.count_SIGCHLD++;
|
// G.count_SIGCHLD++;
|
||||||
// break;
|
// break;
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
|
//TODO: add putchar('\n') also when we detect that child was killed (sleep 5 + ^C)
|
||||||
|
/* Builtin was ^C'ed, make it look prettier: */
|
||||||
bb_putchar('\n');
|
bb_putchar('\n');
|
||||||
G.flag_SIGINT = 1;
|
G.flag_SIGINT = 1;
|
||||||
break;
|
break;
|
||||||
@ -2284,37 +2295,46 @@ void re_execute_shell(char ***to_free, const char *s, char *argv0, char **argv);
|
|||||||
|
|
||||||
static void reset_traps_to_defaults(void)
|
static void reset_traps_to_defaults(void)
|
||||||
{
|
{
|
||||||
enum {
|
/* This function is always called in a child shell
|
||||||
JOBSIGS = (1 << SIGTTIN) | (1 << SIGTTOU) | (1 << SIGTSTP)
|
* after fork (not vfork, NOMMU doesn't use this function).
|
||||||
};
|
|
||||||
unsigned sig;
|
|
||||||
|
|
||||||
if (!G.traps && !(G.non_DFL_mask & JOBSIGS))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* This function is always called in a child shell.
|
|
||||||
* Child shells are not interactive.
|
* Child shells are not interactive.
|
||||||
* SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
|
* SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
|
||||||
* Testcase: (while :; do :; done) + ^Z should background.
|
* Testcase: (while :; do :; done) + ^Z should background.
|
||||||
|
* Same goes for SIGTERM, SIGHUP, SIGINT.
|
||||||
*/
|
*/
|
||||||
G.non_DFL_mask &= ~JOBSIGS;
|
unsigned sig;
|
||||||
sigdelset(&G.blocked_set, SIGTTIN);
|
unsigned mask;
|
||||||
sigdelset(&G.blocked_set, SIGTTOU);
|
|
||||||
sigdelset(&G.blocked_set, SIGTSTP);
|
|
||||||
|
|
||||||
if (G.traps) for (sig = 0; sig < NSIG; sig++) {
|
if (!G.traps && !(G.non_DFL_mask & SPECIAL_INTERACTIVE_SIGS))
|
||||||
if (!G.traps[sig]) {
|
return;
|
||||||
|
|
||||||
|
/* Stupid. It can be done with *single* &= op, but we can't use
|
||||||
|
* the fact that G.blocked_set is implemented as a bitmask... */
|
||||||
|
mask = (SPECIAL_INTERACTIVE_SIGS >> 1);
|
||||||
|
sig = 1;
|
||||||
|
while (1) {
|
||||||
|
if (mask & 1)
|
||||||
|
sigdelset(&G.blocked_set, sig);
|
||||||
|
mask >>= 1;
|
||||||
|
if (!mask)
|
||||||
|
break;
|
||||||
|
sig++;
|
||||||
|
}
|
||||||
|
|
||||||
|
G.non_DFL_mask &= ~SPECIAL_INTERACTIVE_SIGS;
|
||||||
|
mask = G.non_DFL_mask;
|
||||||
|
if (G.traps) for (sig = 0; sig < NSIG; sig++, mask >>= 1) {
|
||||||
|
if (!G.traps[sig])
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
free(G.traps[sig]);
|
free(G.traps[sig]);
|
||||||
G.traps[sig] = NULL;
|
G.traps[sig] = NULL;
|
||||||
/* There is no signal for 0 (EXIT) */
|
/* There is no signal for 0 (EXIT) */
|
||||||
if (sig == 0)
|
if (sig == 0)
|
||||||
continue;
|
continue;
|
||||||
/* there was a trap handler, we are removing it
|
/* There was a trap handler, we are removing it.
|
||||||
* (if sig has non-DFL handling,
|
* But if sig still has non-DFL handling,
|
||||||
* we don't need to do anything) */
|
* we should not unblock it. */
|
||||||
if (sig < 32 && (G.non_DFL_mask & (1 << sig)))
|
if (mask & 1)
|
||||||
continue;
|
continue;
|
||||||
sigdelset(&G.blocked_set, sig);
|
sigdelset(&G.blocked_set, sig);
|
||||||
}
|
}
|
||||||
@ -5740,17 +5760,8 @@ static void block_signals(int second_time)
|
|||||||
unsigned mask;
|
unsigned mask;
|
||||||
|
|
||||||
mask = (1 << SIGQUIT);
|
mask = (1 << SIGQUIT);
|
||||||
if (G_interactive_fd) {
|
if (G_interactive_fd)
|
||||||
mask = 0
|
mask = (1 << SIGQUIT) | SPECIAL_INTERACTIVE_SIGS;
|
||||||
| (1 << SIGQUIT)
|
|
||||||
| (1 << SIGTERM)
|
|
||||||
//TODO | (1 << SIGHUP)
|
|
||||||
#if ENABLE_HUSH_JOB
|
|
||||||
| (1 << SIGTTIN) | (1 << SIGTTOU) | (1 << SIGTSTP)
|
|
||||||
#endif
|
|
||||||
| (1 << SIGINT)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
G.non_DFL_mask = mask;
|
G.non_DFL_mask = mask;
|
||||||
|
|
||||||
if (!second_time)
|
if (!second_time)
|
||||||
|
Loading…
Reference in New Issue
Block a user