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:
parent
bf2af9acb2
commit
8d7be232a3
85
shell/hush.c
85
shell/hush.c
@ -69,7 +69,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Debug build knobs */
|
||||
/* Build knobs */
|
||||
#define LEAK_HUNTING 0
|
||||
#define BUILD_AS_NOMMU 0
|
||||
/* Enable/disable sanity checks. Ok to enable in production,
|
||||
@ -77,6 +77,13 @@
|
||||
* Keeping 1 for now even in released versions.
|
||||
*/
|
||||
#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
|
||||
@ -485,8 +492,11 @@ struct globals {
|
||||
struct function *top_func;
|
||||
#endif
|
||||
/* Signal and trap handling */
|
||||
// unsigned count_SIGCHLD;
|
||||
// unsigned handled_SIGCHLD;
|
||||
#if ENABLE_HUSH_FAST
|
||||
unsigned count_SIGCHLD;
|
||||
unsigned handled_SIGCHLD;
|
||||
smallint last_waitpid_was_0;
|
||||
#endif
|
||||
/* which signals have non-DFL handler (even with no traps set)? */
|
||||
unsigned non_DFL_mask;
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
enum {
|
||||
@ -1067,10 +1077,13 @@ enum {
|
||||
#endif
|
||||
};
|
||||
|
||||
//static void SIGCHLD_handler(int sig UNUSED_PARAM)
|
||||
//{
|
||||
// G.count_SIGCHLD++;
|
||||
//}
|
||||
#if ENABLE_HUSH_FAST
|
||||
static void SIGCHLD_handler(int sig UNUSED_PARAM)
|
||||
{
|
||||
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
|
||||
|
||||
@ -1158,9 +1171,12 @@ static int check_and_run_traps(int sig)
|
||||
}
|
||||
/* not a trap: special action */
|
||||
switch (sig) {
|
||||
// case SIGCHLD:
|
||||
// G.count_SIGCHLD++;
|
||||
// break;
|
||||
#if ENABLE_HUSH_FAST
|
||||
case SIGCHLD:
|
||||
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:
|
||||
/* Builtin was ^C'ed, make it look prettier: */
|
||||
bb_putchar('\n');
|
||||
@ -2665,6 +2681,10 @@ static void setup_heredoc(struct redir_struct *redir)
|
||||
#endif
|
||||
}
|
||||
/* 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();
|
||||
#if !BB_MMU
|
||||
free(to_free);
|
||||
@ -3273,9 +3293,16 @@ static int checkjobs(struct pipe* fg_pipe)
|
||||
debug_printf_jobs("checkjobs %p\n", fg_pipe);
|
||||
|
||||
errno = 0;
|
||||
// if (G.handled_SIGCHLD == G.count_SIGCHLD)
|
||||
// /* avoid doing syscall, nothing there anyway */
|
||||
// return rcode;
|
||||
#if ENABLE_HUSH_FAST
|
||||
if (G.handled_SIGCHLD == G.count_SIGCHLD) {
|
||||
//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;
|
||||
if (fg_pipe == NULL)
|
||||
@ -3294,13 +3321,20 @@ static int checkjobs(struct pipe* fg_pipe)
|
||||
int i;
|
||||
int dead;
|
||||
|
||||
// i = G.count_SIGCHLD;
|
||||
#if ENABLE_HUSH_FAST
|
||||
i = G.count_SIGCHLD;
|
||||
#endif
|
||||
childpid = waitpid(-1, &status, attributes);
|
||||
if (childpid <= 0) {
|
||||
if (childpid && errno != ECHILD)
|
||||
bb_perror_msg("waitpid");
|
||||
// else /* Until next SIGCHLD, waitpid's are useless */
|
||||
// G.handled_SIGCHLD = i;
|
||||
#if ENABLE_HUSH_FAST
|
||||
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;
|
||||
}
|
||||
dead = WIFEXITED(status) || WIFSIGNALED(status);
|
||||
@ -3696,6 +3730,10 @@ static int run_pipe(struct pipe *pi)
|
||||
}
|
||||
|
||||
/* 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();
|
||||
#if !BB_MMU
|
||||
/* Clean up after vforked child */
|
||||
@ -4861,6 +4899,10 @@ static FILE *generate_stream_from_string(const char *s)
|
||||
}
|
||||
|
||||
/* 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();
|
||||
#if !BB_MMU
|
||||
free(to_free);
|
||||
@ -5990,9 +6032,14 @@ static void block_signals(int second_time)
|
||||
second_time ? NULL : &G.inherited_set);
|
||||
/* POSIX allows shell to re-enable SIGCHLD
|
||||
* 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)
|
||||
signal(SIGCHLD, SIG_DFL); // SIGCHLD_handler);
|
||||
signal(SIGCHLD, SIGCHLD_handler);
|
||||
#else
|
||||
if (!second_time)
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_HUSH_JOB
|
||||
|
Loading…
Reference in New Issue
Block a user