changeset 10083:9b5dc36de6db

6859421 Several x86 platforms (DomU, B100s/x, ELX nic based systems) all hang at DEBUG enabled miniroot boot
author Roger A. Faulkner <Roger.Faulkner@Sun.COM>
date Tue, 14 Jul 2009 14:58:36 -0700
parents 435eef142c62
children 783f82a0c357
files usr/src/cmd/init/init.c
diffstat 1 files changed, 28 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/init/init.c	Tue Jul 14 16:27:17 2009 -0400
+++ b/usr/src/cmd/init/init.c	Tue Jul 14 14:58:36 2009 -0700
@@ -939,10 +939,10 @@
 
 	console(B_FALSE, "Requesting maintenance mode\n"
 	    "(See /lib/svc/share/README for additional information.)\n");
-	(void) sigset(SIGCLD, SIG_DFL);
+	(void) sighold(SIGCLD);
 	while ((su_process = efork(M_OFF, NULLPROC, NOCLEANUP)) == NO_ROOM)
 		(void) pause();
-	(void) sigset(SIGCLD, childeath);
+	(void) sigrelse(SIGCLD);
 	if (su_process == NULLPROC) {
 		int fd;
 
@@ -1394,7 +1394,7 @@
 	/*
 	 * Spawn a child process to execute this command.
 	 */
-	(void) sigset(SIGCLD, SIG_DFL);
+	(void) sighold(SIGCLD);
 	oprocess = process;
 	while ((process = efork(cmd->c_action, oprocess, modes)) == NO_ROOM)
 		(void) pause();
@@ -1453,7 +1453,7 @@
 
 	st_write();
 
-	(void) sigset(SIGCLD, childeath);
+	(void) sigrelse(SIGCLD);
 }
 
 /*
@@ -1890,10 +1890,10 @@
 {
 	struct PROC_TABLE	*process;
 
-	(void) sigset(SIGCLD, SIG_DFL);
+	(void) sighold(SIGCLD);
 	while ((process = efork(M_OFF, NULLPROC, 0)) == NO_ROOM)
 		(void) pause();
-	(void) sigset(SIGCLD, childeath);
+	(void) sigrelse(SIGCLD);
 
 	if (process == NULLPROC) {
 		/*
@@ -2080,7 +2080,7 @@
 			 * until after there has been an chance to check it.
 			 */
 			if (process = findpslot(&cmd)) {
-				(void) sigset(SIGCLD, SIG_DFL);
+				(void) sighold(SIGCLD);
 				(void) snprintf(svc_aux, SVC_AUX_SIZE,
 				    INITTAB_ENTRY_ID_STR_FORMAT, cmd.c_id);
 				(void) snprintf(init_svc_fmri, SVC_FMRI_SIZE,
@@ -2098,7 +2098,7 @@
 				    (NAMED|NOCLEANUP))) == NO_ROOM;
 				    /* CSTYLED */)
 					;
-				(void) sigset(SIGCLD, childeath);
+				(void) sigrelse(SIGCLD);
 
 				if (process == NULLPROC) {
 					maxfiles = ulimit(UL_GDESLIM, 0);
@@ -2355,22 +2355,14 @@
  * to do and return, otherwise the child will be waited for.
  */
 static void
-childeath_single()
+childeath_single(pid_t pid, int status)
 {
 	struct PROC_TABLE	*process;
 	struct pidlist		*pp;
-	pid_t			pid;
-	int			status;
 
 	/*
-	 * Perform wait to get the process id of the child that died and
-	 * then scan the process table to see if we are interested in
-	 * this process. NOTE: if a super-user sends the SIGCLD signal
-	 * to init, the following wait will not immediately return and
-	 * init will be inoperative until one of its child really does die.
+	 * Scan the process table to see if we are interested in this process.
 	 */
-	pid = wait(&status);
-
 	for (process = proc_table;
 	    (process < proc_table + num_proc); process++) {
 		if ((process->p_flags & (LIVING|OCCUPIED)) ==
@@ -2425,11 +2417,11 @@
 static void
 childeath(int signo)
 {
-	siginfo_t info;
-
-	while ((waitid(P_ALL, (id_t)0, &info, WEXITED|WNOHANG|WNOWAIT) == 0) &&
-	    info.si_pid != 0)
-		childeath_single();
+	pid_t pid;
+	int status;
+
+	while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
+		childeath_single(pid, status);
 }
 
 static void
@@ -2448,13 +2440,8 @@
  * otherwise it searches for a free slot.  Regardless of how it was called,
  * it returns the pointer to the proc_table entry
  *
- * The SIGCLD handler is set to default (SIG_DFL) before calling efork().
- * This relies on the somewhat obscure SVR2 SIGCLD/SIG_DFL semantic
- * implied by the use of signal(3c).  While the meaning of SIG_DFL for
- * SIGCLD is nominally to ignore the signal, once the signal disposition
- * is set to childeath(), the kernel will post a SIGCLD if a child
- * exited during the period the disposition was SIG_DFL.  It acts more
- * like a signal block.
+ * The SIGCLD signal is blocked (held) before calling efork()
+ * and is unblocked (released) after efork() returns.
  *
  * Ideally, this should be rewritten to use modern signal semantics.
  */
@@ -2464,7 +2451,6 @@
 	pid_t	childpid;
 	struct PROC_TABLE *proc;
 	int		i;
-	void (*oldroutine)();
 	/*
 	 * Freshen up the proc_table, removing any entries for dead processes
 	 * that don't have NOCLEANUP set.  Perform the necessary accounting.
@@ -2494,13 +2480,13 @@
 		setimer(5);
 
 		/*
-		 * Wait for some children to die.  Since efork() is normally
-		 * called with SIGCLD in the default state, reset it to catch
-		 * so that child death signals can come in.
+		 * Wait for some children to die.  Since efork()
+		 * is always called with SIGCLD blocked, unblock
+		 * it here so that child death signals can come in.
 		 */
-		oldroutine = sigset(SIGCLD, childeath);
+		(void) sigrelse(SIGCLD);
 		(void) pause();
-		(void) sigset(SIGCLD, oldroutine);
+		(void) sighold(SIGCLD);
 		setimer(0);
 	}
 
@@ -2851,7 +2837,7 @@
 	 * '/', thus when a ' ', '\t', '\n', or '\0' is found, "ptr" will
 	 * point to the last element of the pathname.
 	 */
-	for (ptr = string; *string != ' ' && *string != '\t' && 
+	for (ptr = string; *string != ' ' && *string != '\t' &&
 	    *string != '\n' && *string != '\0'; string++) {
 		if (*string == '/')
 			ptr = string+1;
@@ -3765,7 +3751,7 @@
 	pid_t	pid;
 	short	status;
 
-	(void) sigset(SIGCLD, SIG_DFL);
+	(void) sighold(SIGCLD);
 	Gchild = 0;	/* Note - Safe to do this here since no SIGCLDs */
 	(void) sighold(SIGPOLL);
 	savep = p = Plhead;
@@ -3795,7 +3781,7 @@
 		p = p->pl_next;
 	}
 	(void) sigrelse(SIGPOLL);
-	(void) sigset(SIGCLD, childeath);
+	(void) sigrelse(SIGCLD);
 }
 
 
@@ -4420,8 +4406,8 @@
 		    "Template activation failed; not starting \"%s\" in "
 		    "proper contract.\n", cline);
 
-	/* Hold SIGCHLD so we can wait if necessary. */
-	(void) sighold(SIGCHLD);
+	/* Hold SIGCLD so we can wait if necessary. */
+	(void) sighold(SIGCLD);
 
 	while ((pid = fork()) < 0) {
 		if (errno == EPERM) {
@@ -4491,7 +4477,7 @@
 	if (old_ctid != 0)
 		(void) ct_pr_tmpl_set_transfer(tmpl, 0);
 
-	(void) sigrelse(SIGCHLD);
+	(void) sigrelse(SIGCLD);
 
 	return (0);
 }