diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-05-12 23:06:20 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-05-12 23:06:20 +0200 |
| commit | 0806e401d6747c391fa0427e0ccba9951f9a1c3d (patch) | |
| tree | b64a92ccbe311f699462c48fd2737e3539450238 /shell | |
| parent | b1ab283f0b6acc6610d64ec33a50c7b16e517797 (diff) | |
| download | busybox-w32-0806e401d6747c391fa0427e0ccba9951f9a1c3d.tar.gz busybox-w32-0806e401d6747c391fa0427e0ccba9951f9a1c3d.tar.bz2 busybox-w32-0806e401d6747c391fa0427e0ccba9951f9a1c3d.zip | |
hush: install signal handlers with filled sigmask
function old new delta
install_sighandler - 39 +39
hush_main 1001 1031 +30
builtin_trap 386 392 +6
install_sighandlers 121 123 +2
switch_off_special_sigs 87 86 -1
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 3/1 up/down: 77/-1) Total: 76 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/shell/hush.c b/shell/hush.c index 132b974f0..4c348ec2b 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -815,6 +815,7 @@ struct globals { | |||
| 815 | unsigned long memleak_value; | 815 | unsigned long memleak_value; |
| 816 | int debug_indent; | 816 | int debug_indent; |
| 817 | #endif | 817 | #endif |
| 818 | struct sigaction sa; | ||
| 818 | char user_input_buf[ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 2]; | 819 | char user_input_buf[ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 2]; |
| 819 | }; | 820 | }; |
| 820 | #define G (*ptr_to_globals) | 821 | #define G (*ptr_to_globals) |
| @@ -823,6 +824,9 @@ struct globals { | |||
| 823 | * is global, thus "G." prefix is a useful hint */ | 824 | * is global, thus "G." prefix is a useful hint */ |
| 824 | #define INIT_G() do { \ | 825 | #define INIT_G() do { \ |
| 825 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 826 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
| 827 | /* memset(&G.sa, 0, sizeof(G.sa)); */ \ | ||
| 828 | sigfillset(&G.sa.sa_mask); \ | ||
| 829 | G.sa.sa_flags = SA_RESTART; \ | ||
| 826 | } while (0) | 830 | } while (0) |
| 827 | 831 | ||
| 828 | 832 | ||
| @@ -1414,9 +1418,6 @@ static void restore_G_args(save_arg_t *sv, char **argv) | |||
| 1414 | * Standard says "When a subshell is entered, traps that are not being ignored | 1418 | * Standard says "When a subshell is entered, traps that are not being ignored |
| 1415 | * are set to the default actions". bash interprets it so that traps which | 1419 | * are set to the default actions". bash interprets it so that traps which |
| 1416 | * are set to '' (ignore) are NOT reset to defaults. We do the same. | 1420 | * are set to '' (ignore) are NOT reset to defaults. We do the same. |
| 1417 | * | ||
| 1418 | * TODO: don't use signal() to install sighandlers: need to mask ALL signals | ||
| 1419 | * while handler runs. I saw signal nesting in one strace, race window isn't small. | ||
| 1420 | */ | 1421 | */ |
| 1421 | enum { | 1422 | enum { |
| 1422 | SPECIAL_INTERACTIVE_SIGS = 0 | 1423 | SPECIAL_INTERACTIVE_SIGS = 0 |
| @@ -1444,6 +1445,24 @@ static void record_pending_signo(int sig) | |||
| 1444 | #endif | 1445 | #endif |
| 1445 | } | 1446 | } |
| 1446 | 1447 | ||
| 1448 | static sighandler_t install_sighandler(int sig, sighandler_t handler) | ||
| 1449 | { | ||
| 1450 | struct sigaction old_sa; | ||
| 1451 | |||
| 1452 | /* We could use signal() to install handlers... almost: | ||
| 1453 | * except that we need to mask ALL signals while handlers run. | ||
| 1454 | * I saw signal nesting in strace, race window isn't small. | ||
| 1455 | * SA_RESTART is also needed, but in Linux, signal() | ||
| 1456 | * sets SA_RESTART too. | ||
| 1457 | */ | ||
| 1458 | /* memset(&G.sa, 0, sizeof(G.sa)); - already done */ | ||
| 1459 | /* sigfillset(&G.sa.sa_mask); - already done */ | ||
| 1460 | /* G.sa.sa_flags = SA_RESTART; - already done */ | ||
| 1461 | G.sa.sa_handler = handler; | ||
| 1462 | sigaction(sig, &G.sa, &old_sa); | ||
| 1463 | return old_sa.sa_handler; | ||
| 1464 | } | ||
| 1465 | |||
| 1447 | #if ENABLE_HUSH_JOB | 1466 | #if ENABLE_HUSH_JOB |
| 1448 | 1467 | ||
| 1449 | /* After [v]fork, in child: do not restore tty pgrp on xfunc death */ | 1468 | /* After [v]fork, in child: do not restore tty pgrp on xfunc death */ |
| @@ -5451,7 +5470,7 @@ static void switch_off_special_sigs(unsigned mask) | |||
| 5451 | G.traps[sig] = NULL; | 5470 | G.traps[sig] = NULL; |
| 5452 | } | 5471 | } |
| 5453 | /* We are here only if no trap or trap was not '' */ | 5472 | /* We are here only if no trap or trap was not '' */ |
| 5454 | signal(sig, SIG_DFL); | 5473 | install_sighandler(sig, SIG_DFL); |
| 5455 | } | 5474 | } |
| 5456 | } | 5475 | } |
| 5457 | 5476 | ||
| @@ -5496,7 +5515,7 @@ static void reset_traps_to_defaults(void) | |||
| 5496 | /* There is no signal for trap 0 (EXIT) */ | 5515 | /* There is no signal for trap 0 (EXIT) */ |
| 5497 | if (sig == 0) | 5516 | if (sig == 0) |
| 5498 | continue; | 5517 | continue; |
| 5499 | signal(sig, pick_sighandler(sig)); | 5518 | install_sighandler(sig, pick_sighandler(sig)); |
| 5500 | } | 5519 | } |
| 5501 | } | 5520 | } |
| 5502 | 5521 | ||
| @@ -7524,7 +7543,7 @@ static void install_sighandlers(unsigned mask) | |||
| 7524 | sig++; | 7543 | sig++; |
| 7525 | if (!(mask & 1)) | 7544 | if (!(mask & 1)) |
| 7526 | continue; | 7545 | continue; |
| 7527 | old_handler = signal(sig, pick_sighandler(sig)); | 7546 | old_handler = install_sighandler(sig, pick_sighandler(sig)); |
| 7528 | /* POSIX allows shell to re-enable SIGCHLD | 7547 | /* POSIX allows shell to re-enable SIGCHLD |
| 7529 | * even if it was SIG_IGN on entry. | 7548 | * even if it was SIG_IGN on entry. |
| 7530 | * Therefore we skip IGN check for it: | 7549 | * Therefore we skip IGN check for it: |
| @@ -7533,7 +7552,7 @@ static void install_sighandlers(unsigned mask) | |||
| 7533 | continue; | 7552 | continue; |
| 7534 | if (old_handler == SIG_IGN) { | 7553 | if (old_handler == SIG_IGN) { |
| 7535 | /* oops... restore back to IGN, and record this fact */ | 7554 | /* oops... restore back to IGN, and record this fact */ |
| 7536 | signal(sig, old_handler); | 7555 | install_sighandler(sig, old_handler); |
| 7537 | if (!G.traps) | 7556 | if (!G.traps) |
| 7538 | G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); | 7557 | G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); |
| 7539 | free(G.traps[sig]); | 7558 | free(G.traps[sig]); |
| @@ -7854,7 +7873,7 @@ int hush_main(int argc, char **argv) | |||
| 7854 | for (sig = 1; sig < NSIG; sig++) { | 7873 | for (sig = 1; sig < NSIG; sig++) { |
| 7855 | if (empty_trap_mask & (1LL << sig)) { | 7874 | if (empty_trap_mask & (1LL << sig)) { |
| 7856 | G.traps[sig] = xzalloc(1); /* == xstrdup(""); */ | 7875 | G.traps[sig] = xzalloc(1); /* == xstrdup(""); */ |
| 7857 | signal(sig, SIG_IGN); | 7876 | install_sighandler(sig, SIG_IGN); |
| 7858 | } | 7877 | } |
| 7859 | } | 7878 | } |
| 7860 | } | 7879 | } |
| @@ -8389,7 +8408,7 @@ static int FAST_FUNC builtin_trap(char **argv) | |||
| 8389 | else | 8408 | else |
| 8390 | /* We are removing trap handler */ | 8409 | /* We are removing trap handler */ |
| 8391 | handler = pick_sighandler(sig); | 8410 | handler = pick_sighandler(sig); |
| 8392 | signal(sig, handler); | 8411 | install_sighandler(sig, handler); |
| 8393 | } | 8412 | } |
| 8394 | return ret; | 8413 | return ret; |
| 8395 | } | 8414 | } |
