aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-05-25 16:38:32 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-05-25 16:38:32 +0200
commit8d7be232a39c6fb85b6870d1a705ceca48bed869 (patch)
treec7d2c47f8b18f02fa13bf1418a5139a3e0f00817
parentbf2af9acb28ed6d8bbe351d669daaa140d0239f0 (diff)
downloadbusybox-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.c85
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 */
1056enum { 1066enum {
@@ -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//{ 1081static 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