hush: fix SIGCHLD counting code, but keep it disabled for now.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-05-25 16:38:32 +02:00
parent bf2af9acb2
commit 8d7be232a3

View File

@ -69,7 +69,7 @@
#endif #endif
/* Debug build knobs */ /* Build knobs */
#define LEAK_HUNTING 0 #define LEAK_HUNTING 0
#define BUILD_AS_NOMMU 0 #define BUILD_AS_NOMMU 0
/* Enable/disable sanity checks. Ok to enable in production, /* Enable/disable sanity checks. Ok to enable in production,
@ -77,6 +77,13 @@
* Keeping 1 for now even in released versions. * Keeping 1 for now even in released versions.
*/ */
#define HUSH_DEBUG 1 #define HUSH_DEBUG 1
/* Slightly bigger (+200 bytes), but faster hush.
* So far it only enables a trick with counting SIGCHLDs and forks,
* which allows us to do fewer waitpid's.
* (we can detect a case where neither forks were done nor SIGCHLDs happened
* and therefore waitpid will return the same result as last time)
*/
#define ENABLE_HUSH_FAST 0
#if BUILD_AS_NOMMU #if BUILD_AS_NOMMU
@ -485,8 +492,11 @@ struct globals {
struct function *top_func; struct function *top_func;
#endif #endif
/* Signal and trap handling */ /* Signal and trap handling */
// unsigned count_SIGCHLD; #if ENABLE_HUSH_FAST
// unsigned handled_SIGCHLD; unsigned count_SIGCHLD;
unsigned handled_SIGCHLD;
smallint last_waitpid_was_0;
#endif
/* which signals have non-DFL handler (even with no traps set)? */ /* which signals have non-DFL handler (even with no traps set)? */
unsigned non_DFL_mask; unsigned non_DFL_mask;
char **traps; /* char *traps[NSIG] */ char **traps; /* char *traps[NSIG] */
@ -1050,7 +1060,7 @@ static void restore_G_args(save_arg_t *sv, char **argv)
* Restore blocked signal set to one inherited by shell just prior to exec. * Restore blocked signal set to one inherited by shell just prior to exec.
* *
* Note: as a result, we do not use signal handlers much. The only uses * Note: as a result, we do not use signal handlers much. The only uses
* are to count SIGCHLDs [disabled - bug somewhere, + bloat] * are to count SIGCHLDs
* and to restore tty pgrp on signal-induced exit. * and to restore tty pgrp on signal-induced exit.
*/ */
enum { enum {
@ -1067,10 +1077,13 @@ enum {
#endif #endif
}; };
//static void SIGCHLD_handler(int sig UNUSED_PARAM) #if ENABLE_HUSH_FAST
//{ static void SIGCHLD_handler(int sig UNUSED_PARAM)
// G.count_SIGCHLD++; {
//} G.count_SIGCHLD++;
//bb_error_msg("[%d] SIGCHLD_handler: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
}
#endif
#if ENABLE_HUSH_JOB #if ENABLE_HUSH_JOB
@ -1158,9 +1171,12 @@ static int check_and_run_traps(int sig)
} }
/* not a trap: special action */ /* not a trap: special action */
switch (sig) { switch (sig) {
// case SIGCHLD: #if ENABLE_HUSH_FAST
// G.count_SIGCHLD++; case SIGCHLD:
// break; G.count_SIGCHLD++;
//bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
break;
#endif
case SIGINT: case SIGINT:
/* Builtin was ^C'ed, make it look prettier: */ /* Builtin was ^C'ed, make it look prettier: */
bb_putchar('\n'); bb_putchar('\n');
@ -2665,6 +2681,10 @@ static void setup_heredoc(struct redir_struct *redir)
#endif #endif
} }
/* parent */ /* parent */
#if ENABLE_HUSH_FAST
G.count_SIGCHLD++;
//bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
#endif
enable_restore_tty_pgrp_on_exit(); enable_restore_tty_pgrp_on_exit();
#if !BB_MMU #if !BB_MMU
free(to_free); free(to_free);
@ -3273,9 +3293,16 @@ static int checkjobs(struct pipe* fg_pipe)
debug_printf_jobs("checkjobs %p\n", fg_pipe); debug_printf_jobs("checkjobs %p\n", fg_pipe);
errno = 0; errno = 0;
// if (G.handled_SIGCHLD == G.count_SIGCHLD) #if ENABLE_HUSH_FAST
// /* avoid doing syscall, nothing there anyway */ if (G.handled_SIGCHLD == G.count_SIGCHLD) {
// return rcode; //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);
/* avoid doing syscall, nothing there anyway */
if (G.last_waitpid_was_0)
return 0;
errno = ECHILD;
return -1;
}
#endif
attributes = WUNTRACED; attributes = WUNTRACED;
if (fg_pipe == NULL) if (fg_pipe == NULL)
@ -3294,13 +3321,20 @@ static int checkjobs(struct pipe* fg_pipe)
int i; int i;
int dead; int dead;
// i = G.count_SIGCHLD; #if ENABLE_HUSH_FAST
i = G.count_SIGCHLD;
#endif
childpid = waitpid(-1, &status, attributes); childpid = waitpid(-1, &status, attributes);
if (childpid <= 0) { if (childpid <= 0) {
if (childpid && errno != ECHILD) if (childpid && errno != ECHILD)
bb_perror_msg("waitpid"); bb_perror_msg("waitpid");
// else /* Until next SIGCHLD, waitpid's are useless */ #if ENABLE_HUSH_FAST
// G.handled_SIGCHLD = i; else { /* Until next SIGCHLD, waitpid's are useless */
G.last_waitpid_was_0 = (childpid == 0);
G.handled_SIGCHLD = i;
//bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
}
#endif
break; break;
} }
dead = WIFEXITED(status) || WIFSIGNALED(status); dead = WIFEXITED(status) || WIFSIGNALED(status);
@ -3696,6 +3730,10 @@ static int run_pipe(struct pipe *pi)
} }
/* parent or error */ /* parent or error */
#if ENABLE_HUSH_FAST
G.count_SIGCHLD++;
//bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
#endif
enable_restore_tty_pgrp_on_exit(); enable_restore_tty_pgrp_on_exit();
#if !BB_MMU #if !BB_MMU
/* Clean up after vforked child */ /* Clean up after vforked child */
@ -4861,6 +4899,10 @@ static FILE *generate_stream_from_string(const char *s)
} }
/* parent */ /* parent */
#if ENABLE_HUSH_FAST
G.count_SIGCHLD++;
//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);
#endif
enable_restore_tty_pgrp_on_exit(); enable_restore_tty_pgrp_on_exit();
#if !BB_MMU #if !BB_MMU
free(to_free); free(to_free);
@ -5990,9 +6032,14 @@ static void block_signals(int second_time)
second_time ? NULL : &G.inherited_set); second_time ? NULL : &G.inherited_set);
/* POSIX allows shell to re-enable SIGCHLD /* POSIX allows shell to re-enable SIGCHLD
* even if it was SIG_IGN on entry */ * even if it was SIG_IGN on entry */
// G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ #if ENABLE_HUSH_FAST
G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
if (!second_time) if (!second_time)
signal(SIGCHLD, SIG_DFL); // SIGCHLD_handler); signal(SIGCHLD, SIGCHLD_handler);
#else
if (!second_time)
signal(SIGCHLD, SIG_DFL);
#endif
} }
#if ENABLE_HUSH_JOB #if ENABLE_HUSH_JOB