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 |
