diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-25 16:38:32 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-25 16:38:32 +0200 |
commit | 8d7be232a39c6fb85b6870d1a705ceca48bed869 (patch) | |
tree | c7d2c47f8b18f02fa13bf1418a5139a3e0f00817 | |
parent | bf2af9acb28ed6d8bbe351d669daaa140d0239f0 (diff) | |
download | busybox-w32-8d7be232a39c6fb85b6870d1a705ceca48bed869.tar.gz busybox-w32-8d7be232a39c6fb85b6870d1a705ceca48bed869.tar.bz2 busybox-w32-8d7be232a39c6fb85b6870d1a705ceca48bed869.zip |
hush: fix SIGCHLD counting code, but keep it disabled for now.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush.c | 85 |
1 files changed, 66 insertions, 19 deletions
diff --git a/shell/hush.c b/shell/hush.c index acc8ef944..fd839d061 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -69,7 +69,7 @@ | |||
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | 71 | ||
72 | /* Debug build knobs */ | 72 | /* Build knobs */ |
73 | #define LEAK_HUNTING 0 | 73 | #define LEAK_HUNTING 0 |
74 | #define BUILD_AS_NOMMU 0 | 74 | #define BUILD_AS_NOMMU 0 |
75 | /* Enable/disable sanity checks. Ok to enable in production, | 75 | /* Enable/disable sanity checks. Ok to enable in production, |
@@ -77,6 +77,13 @@ | |||
77 | * Keeping 1 for now even in released versions. | 77 | * Keeping 1 for now even in released versions. |
78 | */ | 78 | */ |
79 | #define HUSH_DEBUG 1 | 79 | #define HUSH_DEBUG 1 |
80 | /* Slightly bigger (+200 bytes), but faster hush. | ||
81 | * So far it only enables a trick with counting SIGCHLDs and forks, | ||
82 | * which allows us to do fewer waitpid's. | ||
83 | * (we can detect a case where neither forks were done nor SIGCHLDs happened | ||
84 | * and therefore waitpid will return the same result as last time) | ||
85 | */ | ||
86 | #define ENABLE_HUSH_FAST 0 | ||
80 | 87 | ||
81 | 88 | ||
82 | #if BUILD_AS_NOMMU | 89 | #if BUILD_AS_NOMMU |
@@ -485,8 +492,11 @@ struct globals { | |||
485 | struct function *top_func; | 492 | struct function *top_func; |
486 | #endif | 493 | #endif |
487 | /* Signal and trap handling */ | 494 | /* Signal and trap handling */ |
488 | // unsigned count_SIGCHLD; | 495 | #if ENABLE_HUSH_FAST |
489 | // unsigned handled_SIGCHLD; | 496 | unsigned count_SIGCHLD; |
497 | unsigned handled_SIGCHLD; | ||
498 | smallint last_waitpid_was_0; | ||
499 | #endif | ||
490 | /* which signals have non-DFL handler (even with no traps set)? */ | 500 | /* which signals have non-DFL handler (even with no traps set)? */ |
491 | unsigned non_DFL_mask; | 501 | unsigned non_DFL_mask; |
492 | char **traps; /* char *traps[NSIG] */ | 502 | char **traps; /* char *traps[NSIG] */ |
@@ -1050,7 +1060,7 @@ static void restore_G_args(save_arg_t *sv, char **argv) | |||
1050 | * Restore blocked signal set to one inherited by shell just prior to exec. | 1060 | * Restore blocked signal set to one inherited by shell just prior to exec. |
1051 | * | 1061 | * |
1052 | * Note: as a result, we do not use signal handlers much. The only uses | 1062 | * Note: as a result, we do not use signal handlers much. The only uses |
1053 | * are to count SIGCHLDs [disabled - bug somewhere, + bloat] | 1063 | * are to count SIGCHLDs |
1054 | * and to restore tty pgrp on signal-induced exit. | 1064 | * and to restore tty pgrp on signal-induced exit. |
1055 | */ | 1065 | */ |
1056 | enum { | 1066 | enum { |
@@ -1067,10 +1077,13 @@ enum { | |||
1067 | #endif | 1077 | #endif |
1068 | }; | 1078 | }; |
1069 | 1079 | ||
1070 | //static void SIGCHLD_handler(int sig UNUSED_PARAM) | 1080 | #if ENABLE_HUSH_FAST |
1071 | //{ | 1081 | static void SIGCHLD_handler(int sig UNUSED_PARAM) |
1072 | // G.count_SIGCHLD++; | 1082 | { |
1073 | //} | 1083 | G.count_SIGCHLD++; |
1084 | //bb_error_msg("[%d] SIGCHLD_handler: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); | ||
1085 | } | ||
1086 | #endif | ||
1074 | 1087 | ||
1075 | #if ENABLE_HUSH_JOB | 1088 | #if ENABLE_HUSH_JOB |
1076 | 1089 | ||
@@ -1158,9 +1171,12 @@ static int check_and_run_traps(int sig) | |||
1158 | } | 1171 | } |
1159 | /* not a trap: special action */ | 1172 | /* not a trap: special action */ |
1160 | switch (sig) { | 1173 | switch (sig) { |
1161 | // case SIGCHLD: | 1174 | #if ENABLE_HUSH_FAST |
1162 | // G.count_SIGCHLD++; | 1175 | case SIGCHLD: |
1163 | // break; | 1176 | G.count_SIGCHLD++; |
1177 | //bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); | ||
1178 | break; | ||
1179 | #endif | ||
1164 | case SIGINT: | 1180 | case SIGINT: |
1165 | /* Builtin was ^C'ed, make it look prettier: */ | 1181 | /* Builtin was ^C'ed, make it look prettier: */ |
1166 | bb_putchar('\n'); | 1182 | bb_putchar('\n'); |
@@ -2665,6 +2681,10 @@ static void setup_heredoc(struct redir_struct *redir) | |||
2665 | #endif | 2681 | #endif |
2666 | } | 2682 | } |
2667 | /* parent */ | 2683 | /* parent */ |
2684 | #if ENABLE_HUSH_FAST | ||
2685 | G.count_SIGCHLD++; | ||
2686 | //bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); | ||
2687 | #endif | ||
2668 | enable_restore_tty_pgrp_on_exit(); | 2688 | enable_restore_tty_pgrp_on_exit(); |
2669 | #if !BB_MMU | 2689 | #if !BB_MMU |
2670 | free(to_free); | 2690 | free(to_free); |
@@ -3273,9 +3293,16 @@ static int checkjobs(struct pipe* fg_pipe) | |||
3273 | debug_printf_jobs("checkjobs %p\n", fg_pipe); | 3293 | debug_printf_jobs("checkjobs %p\n", fg_pipe); |
3274 | 3294 | ||
3275 | errno = 0; | 3295 | errno = 0; |
3276 | // if (G.handled_SIGCHLD == G.count_SIGCHLD) | 3296 | #if ENABLE_HUSH_FAST |
3277 | // /* avoid doing syscall, nothing there anyway */ | 3297 | if (G.handled_SIGCHLD == G.count_SIGCHLD) { |
3278 | // return rcode; | 3298 | //bb_error_msg("[%d] checkjobs: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d was 0?:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD, G.last_waitpid_was_0); |
3299 | /* avoid doing syscall, nothing there anyway */ | ||
3300 | if (G.last_waitpid_was_0) | ||
3301 | return 0; | ||
3302 | errno = ECHILD; | ||
3303 | return -1; | ||
3304 | } | ||
3305 | #endif | ||
3279 | 3306 | ||
3280 | attributes = WUNTRACED; | 3307 | attributes = WUNTRACED; |
3281 | if (fg_pipe == NULL) | 3308 | if (fg_pipe == NULL) |
@@ -3294,13 +3321,20 @@ static int checkjobs(struct pipe* fg_pipe) | |||
3294 | int i; | 3321 | int i; |
3295 | int dead; | 3322 | int dead; |
3296 | 3323 | ||
3297 | // i = G.count_SIGCHLD; | 3324 | #if ENABLE_HUSH_FAST |
3325 | i = G.count_SIGCHLD; | ||
3326 | #endif | ||
3298 | childpid = waitpid(-1, &status, attributes); | 3327 | childpid = waitpid(-1, &status, attributes); |
3299 | if (childpid <= 0) { | 3328 | if (childpid <= 0) { |
3300 | if (childpid && errno != ECHILD) | 3329 | if (childpid && errno != ECHILD) |
3301 | bb_perror_msg("waitpid"); | 3330 | bb_perror_msg("waitpid"); |
3302 | // else /* Until next SIGCHLD, waitpid's are useless */ | 3331 | #if ENABLE_HUSH_FAST |
3303 | // G.handled_SIGCHLD = i; | 3332 | else { /* Until next SIGCHLD, waitpid's are useless */ |
3333 | G.last_waitpid_was_0 = (childpid == 0); | ||
3334 | G.handled_SIGCHLD = i; | ||
3335 | //bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); | ||
3336 | } | ||
3337 | #endif | ||
3304 | break; | 3338 | break; |
3305 | } | 3339 | } |
3306 | dead = WIFEXITED(status) || WIFSIGNALED(status); | 3340 | dead = WIFEXITED(status) || WIFSIGNALED(status); |
@@ -3696,6 +3730,10 @@ static int run_pipe(struct pipe *pi) | |||
3696 | } | 3730 | } |
3697 | 3731 | ||
3698 | /* parent or error */ | 3732 | /* parent or error */ |
3733 | #if ENABLE_HUSH_FAST | ||
3734 | G.count_SIGCHLD++; | ||
3735 | //bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); | ||
3736 | #endif | ||
3699 | enable_restore_tty_pgrp_on_exit(); | 3737 | enable_restore_tty_pgrp_on_exit(); |
3700 | #if !BB_MMU | 3738 | #if !BB_MMU |
3701 | /* Clean up after vforked child */ | 3739 | /* Clean up after vforked child */ |
@@ -4861,6 +4899,10 @@ static FILE *generate_stream_from_string(const char *s) | |||
4861 | } | 4899 | } |
4862 | 4900 | ||
4863 | /* parent */ | 4901 | /* parent */ |
4902 | #if ENABLE_HUSH_FAST | ||
4903 | G.count_SIGCHLD++; | ||
4904 | //bb_error_msg("[%d] fork in generate_stream_from_string: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); | ||
4905 | #endif | ||
4864 | enable_restore_tty_pgrp_on_exit(); | 4906 | enable_restore_tty_pgrp_on_exit(); |
4865 | #if !BB_MMU | 4907 | #if !BB_MMU |
4866 | free(to_free); | 4908 | free(to_free); |
@@ -5990,9 +6032,14 @@ static void block_signals(int second_time) | |||
5990 | second_time ? NULL : &G.inherited_set); | 6032 | second_time ? NULL : &G.inherited_set); |
5991 | /* POSIX allows shell to re-enable SIGCHLD | 6033 | /* POSIX allows shell to re-enable SIGCHLD |
5992 | * even if it was SIG_IGN on entry */ | 6034 | * even if it was SIG_IGN on entry */ |
5993 | // G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ | 6035 | #if ENABLE_HUSH_FAST |
6036 | G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ | ||
6037 | if (!second_time) | ||
6038 | signal(SIGCHLD, SIGCHLD_handler); | ||
6039 | #else | ||
5994 | if (!second_time) | 6040 | if (!second_time) |
5995 | signal(SIGCHLD, SIG_DFL); // SIGCHLD_handler); | 6041 | signal(SIGCHLD, SIG_DFL); |
6042 | #endif | ||
5996 | } | 6043 | } |
5997 | 6044 | ||
5998 | #if ENABLE_HUSH_JOB | 6045 | #if ENABLE_HUSH_JOB |