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/hush.c | |
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 '')
-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 | } |