svn commit: [25901] trunk/busybox/shell

vda at busybox.net vda at busybox.net
Tue Mar 31 12:03:40 UTC 2009


Author: vda
Date: 2009-03-31 12:03:40 +0000 (Tue, 31 Mar 2009)
New Revision: 25901

Log:
hush: do not reset sighaldlers after fork - instead, prevent them from doing any harm
 if they will be called. saves many sigaction calls on every fork.

function                                             old     new   delta
hush_main                                            887     971     +84
sigexit                                               54      65     +11
run_list                                            2006    2001      -5
maybe_set_sighandler                                  76      50     -26
set_fatal_sighandler                                 186       -    -186
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 2/2 up/down: 95/-217)          Total: -122 bytes



Modified:
   trunk/busybox/shell/hush.c


Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2009-03-31 11:22:57 UTC (rev 25900)
+++ trunk/busybox/shell/hush.c	2009-03-31 12:03:40 UTC (rev 25901)
@@ -493,8 +493,6 @@
 	char **traps; /* char *traps[NSIG] */
 	/* which signals have non-DFL handler (even with no traps set)? */
 	unsigned non_DFL_mask;
-	/* which signals are known to be IGNed on entry to shell? */
-	unsigned IGN_mask;
 	sigset_t blocked_set;
 	sigset_t inherited_set;
 };
@@ -895,66 +893,71 @@
 	}
 }
 
-/* The stuff below needs to be migrated to "Special action" above */
+#if ENABLE_HUSH_JOB
 
-/////* Signals are grouped, we handle them in batches */
-////static void set_misc_sighandler(void (*handler)(int))
-////{
-////	bb_signals(0
-////		+ (1 << SIGINT)
-////		+ (1 << SIGQUIT)
-////		+ (1 << SIGTERM)
-////		, handler);
-////}
+/* Restores tty foreground process group, and exits.
+ * May be called as signal handler for fatal signal
+ * (will faithfully resend signal to itself, producing correct exit state)
+ * or called directly with -EXITCODE.
+ * We also call it if xfunc is exiting. */
+static void sigexit(int sig) NORETURN;
+static void sigexit(int sig)
+{
+	/* Disable all signals: job control, SIGPIPE, etc. */
+	sigprocmask_allsigs(SIG_BLOCK);
 
-#if ENABLE_HUSH_JOB
+#if ENABLE_HUSH_INTERACTIVE
+	/* Careful: we can end up here after [v]fork. Do not restore
+	 * tty pgrp, only top-level shell process does that */
+	if (G.interactive_fd && getpid() == G.root_pid)
+		tcsetpgrp(G.interactive_fd, G.saved_tty_pgrp);
+#endif
 
+	/* Not a signal, just exit */
+	if (sig <= 0)
+		_exit(- sig);
+
+	kill_myself_with_sig(sig); /* does not return */
+}
+
 /* helper */
-static unsigned maybe_set_sighandler(int sig, void (*handler)(int))
+static void maybe_set_sighandler(int sig)
 {
+	void (*handler)(int);
 	/* non_DFL_mask'ed signals are, well, masked,
 	 * no need to set handler for them.
-	 * IGN_mask'ed signals were found to be IGN on entry,
-	 * do not change that -> no need to set handler for them either
 	 */
-	unsigned ign = ((G.IGN_mask|G.non_DFL_mask) >> sig) & 1;
-	if (!ign) {
-		handler = signal(sig, handler);
-		ign = (handler == SIG_IGN);
-		if (ign) /* restore back to IGN! */
+	if (!((G.non_DFL_mask >> sig) & 1)) {
+		handler = signal(sig, sigexit);
+		if (handler == SIG_IGN) /* restore back to IGN! */
 			signal(sig, handler);
 	}
-	return ign << sig; /* pass back knowledge about SIG_IGN */
 }
 /* Used only to set handler to restore pgrp on exit, and to reset it to DFL */
-static void set_fatal_sighandler(void (*handler)(int))
+static void set_fatal_signals_to_sigexit(void)
 {
-	unsigned mask = 0;
-
 	if (HUSH_DEBUG) {
-		mask |= maybe_set_sighandler(SIGILL , handler);
-		mask |= maybe_set_sighandler(SIGFPE , handler);
-		mask |= maybe_set_sighandler(SIGBUS , handler);
-		mask |= maybe_set_sighandler(SIGSEGV, handler);
-		mask |= maybe_set_sighandler(SIGTRAP, handler);
+		maybe_set_sighandler(SIGILL );
+		maybe_set_sighandler(SIGFPE );
+		maybe_set_sighandler(SIGBUS );
+		maybe_set_sighandler(SIGSEGV);
+		maybe_set_sighandler(SIGTRAP);
 	} /* else: hush is perfect. what SEGV? */
 
-	mask |= maybe_set_sighandler(SIGABRT, handler);
+	maybe_set_sighandler(SIGABRT);
 
 	/* bash 3.2 seems to handle these just like 'fatal' ones */
-	mask |= maybe_set_sighandler(SIGPIPE, handler);
-	mask |= maybe_set_sighandler(SIGALRM, handler);
-	mask |= maybe_set_sighandler(SIGHUP , handler);
+	maybe_set_sighandler(SIGPIPE);
+	maybe_set_sighandler(SIGALRM);
+	maybe_set_sighandler(SIGHUP );
 
 	/* if we aren't interactive... but in this case
 	 * we never want to restore pgrp on exit, and this fn is not called */
-	/*mask |= maybe_set_sighandler(SIGTERM, handler); */
-	/*mask |= maybe_set_sighandler(SIGINT , handler); */
-
-	G.IGN_mask = mask;
+	/*maybe_set_sighandler(SIGTERM);*/
+	/*maybe_set_sighandler(SIGINT );*/
 }
 /* Used only to suppress ^Z in `cmd` */
-static void IGN_jobctrl_signals(void)
+static void set_jobctrl_signals_to_IGN(void)
 {
 	bb_signals(0
 		+ (1 << SIGTSTP)
@@ -962,88 +965,11 @@
 		+ (1 << SIGTTOU)
 		, SIG_IGN);
 }
-/* SIGCHLD is special and handled separately */
 
-////static void set_every_sighandler(void (*handler)(int))
-////{
-////	set_fatal_sighandler(handler);
-////	set_jobctrl_sighandler(handler);
-////	set_misc_sighandler(handler);
-////	signal(SIGCHLD, handler);
-////}
-
-////static void handler_ctrl_c(int sig UNUSED_PARAM)
-////{
-////	debug_printf_jobs("got sig %d\n", sig);
-////// as usual we can have all kinds of nasty problems with leaked malloc data here
-////	siglongjmp(G.toplevel_jb, 1);
-////}
-
-////static void handler_ctrl_z(int sig UNUSED_PARAM)
-////{
-////	pid_t pid;
-////
-////	debug_printf_jobs("got tty sig %d in pid %d\n", sig, getpid());
-////
-////	if (!BB_MMU) {
-////		fputs("Sorry, backgrounding (CTRL+Z) of foreground scripts not supported on nommu\n", stderr);
-////		return;
-////	}
-////
-////	pid = fork();
-////	if (pid < 0) /* can't fork. Pretend there was no ctrl-Z */
-////		return;
-////	G.ctrl_z_flag = 1;
-////	if (!pid) { /* child */
-////		if (ENABLE_HUSH_JOB)
-////			die_sleep = 0; /* let nofork's xfuncs die */
-////		bb_setpgrp();
-////		debug_printf_jobs("set pgrp for child %d ok\n", getpid());
-////////		set_every_sighandler(SIG_DFL);
-////		raise(SIGTSTP); /* resend TSTP so that child will be stopped */
-////		debug_printf_jobs("returning in child\n");
-////		/* return to nofork, it will eventually exit now,
-////		 * not return back to shell */
-////		return;
-////	}
-////	/* parent */
-////	/* finish filling up pipe info */
-////	G.toplevel_list->pgrp = pid; /* child is in its own pgrp */
-////	G.toplevel_list->cmds[0].pid = pid;
-////	/* parent needs to longjmp out of running nofork.
-////	 * we will "return" exitcode 0, with child put in background */
-////// as usual we can have all kinds of nasty problems with leaked malloc data here
-////	debug_printf_jobs("siglongjmp in parent\n");
-////	siglongjmp(G.toplevel_jb, 1);
-////}
-
-/* Restores tty foreground process group, and exits.
- * May be called as signal handler for fatal signal
- * (will faithfully resend signal to itself, producing correct exit state)
- * or called directly with -EXITCODE.
- * We also call it if xfunc is exiting. */
-static void sigexit(int sig) NORETURN;
-static void sigexit(int sig)
-{
-	/* Disable all signals: job control, SIGPIPE, etc. */
-	sigprocmask_allsigs(SIG_BLOCK);
-
-#if ENABLE_HUSH_INTERACTIVE
-	if (G.interactive_fd)
-		tcsetpgrp(G.interactive_fd, G.saved_tty_pgrp);
-#endif
-
-	/* Not a signal, just exit */
-	if (sig <= 0)
-		_exit(- sig);
-
-	kill_myself_with_sig(sig); /* does not return */
-}
-
 #else /* !JOB */
 
-#define set_fatal_sighandler(handler) ((void)0)
-#define IGN_jobctrl_signals(handler)  ((void)0)
+#define set_fatal_signals_to_sigexit(handler) ((void)0)
+#define set_jobctrl_signals_to_IGN(handler)  ((void)0)
 
 #endif /* JOB */
 
@@ -1057,11 +983,12 @@
 		free(argv[1]);
 	}
 
-	if (ENABLE_HUSH_JOB) {
-		fflush(NULL); /* flush all streams */
-		sigexit(- (exitcode & 0xff));
-	} else
-		exit(exitcode);
+#if ENABLE_HUSH_JOB
+	fflush(NULL); /* flush all streams */
+	sigexit(- (exitcode & 0xff));
+#else
+	exit(exitcode);
+#endif
 }
 
 
@@ -2641,10 +2568,6 @@
 	 * might include `cmd` runs! Do not rerun it! We *must*
 	 * use argv_expanded if it's non-NULL */
 
-	/* Disable job control signals for shell (parent) and
-	 * for initial child code after fork */
-////	set_jobctrl_sighandler(SIG_IGN);
-
 	/* Going to fork a child per each pipe member */
 	pi->alive_cmds = 0;
 	nextin = 0;
@@ -2677,8 +2600,6 @@
 			 * with pgid == pid_of_first_child_in_pipe */
 			if (G.run_list_level == 1 && G.interactive_fd) {
 				pid_t pgrp;
-				/* Don't do pgrp restore anymore on fatal signals */
-				set_fatal_sighandler(SIG_DFL);
 				pgrp = pi->pgrp;
 				if (pgrp < 0) /* true for 1st process only */
 					pgrp = getpid();
@@ -2698,9 +2619,8 @@
 			setup_redirects(command, NULL);
 
 			/* Restore default handlers just prior to exec */
-////			set_jobctrl_sighandler(SIG_DFL);
-////			set_misc_sighandler(SIG_DFL);
-////			signal(SIGCHLD, SIG_DFL);
+			/*signal(SIGCHLD, SIG_DFL); - so far we don't have any handlers */
+
 			/* Stores to nommu_save list of env vars putenv'ed
 			 * (NOMMU, on MMU we don't need that) */
 			/* cast away volatility... */
@@ -2877,7 +2797,7 @@
 	 * in order to return, no direct "return" statements please.
 	 * This helps to ensure that no memory is leaked. */
 
-//TODO: needs re-thinking
+////TODO: ctrl-Z handling needs re-thinking and re-testing
 
 #if ENABLE_HUSH_JOB
 	/* Example of nested list: "while true; do { sleep 1 | exit 2; } done".
@@ -3674,12 +3594,11 @@
 #endif
 		/* Process substitution is not considered to be usual
 		 * 'command execution'.
-		 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not. */
-////		/* Not needed, we are relying on it being disabled
-////		 * everywhere outside actual command execution. */
-		IGN_jobctrl_signals();
-////		set_misc_sighandler(SIG_DFL);
-		/* Freeing 'head' here would break NOMMU. */
+		 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
+		 */
+		set_jobctrl_signals_to_IGN();
+
+		/* Note: freeing 'head' here would break NOMMU. */
 		_exit(run_list(head));
 	}
 	close(channel[1]);
@@ -4493,13 +4412,8 @@
 		shell_pgrp = getpgrp();
 	}
 
-	/* Ignore job-control and misc signals.  */
-////	set_jobctrl_sighandler(SIG_IGN);
-////	set_misc_sighandler(SIG_IGN);
-//huh?	signal(SIGCHLD, SIG_IGN);
-
 	/* We _must_ restore tty pgrp on fatal signals */
-	set_fatal_sighandler(sigexit);
+	set_fatal_signals_to_sigexit();
 
 	/* Put ourselves in our own process group.  */
 	bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
@@ -4682,7 +4596,6 @@
 		}
 		if (G.interactive_fd) {
 			fcntl(G.interactive_fd, F_SETFD, FD_CLOEXEC);
-////			set_misc_sighandler(SIG_IGN);
 		}
 	}
 	init_signal_mask();



More information about the busybox-cvs mailing list