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
|
#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
|
||||||
|
Loading…
Reference in New Issue
Block a user