Subject: bin/2619: halt or reboot, exec'd from single-user, hangs system.
To: None <gnats-bugs@NetBSD.ORG>
From: None <cgd@cs.cmu.edu>
List: netbsd-bugs
Date: 07/11/1996 15:40:19
>Number:         2619
>Category:       bin
>Synopsis:       halt or reboot, exec'd from single-user, hangs system.
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jul 11 15:50:02 1996
>Last-Modified:
>Originator:     Chris G. Demetriou
>Organization:
Kernel Hackers 'r' Us
>Release:        1.2_ALPHA
>Environment:
System: NetBSD bunnahabhain.pdl.cs.cmu.edu 1.2A NetBSD 1.2A (GENERIC) #37: Tue Jul 9 00:07:21 EDT 1996 cgd@bunnahabhain.pdl.cs.cmu.edu:/nfsmnt/usr8/cgd/mac/trunk-src/sys/arch/alpha/compile/GENERIC alpha


>Description:
	If you 'exec' halt or reboot from single-user mode, it will hang
	the system.

	The problem is that halt/reboot tries to notify other programs
	of system shutdown via kill(-1, SIGTERM), which sends that signal
	to all but the calling process and system processes.  However,
	if halt or reboot is 'exec'ed from single-user mode, there are
	no processes which fit the bill (since init (pid 1) is considered
	a system process), and so ESRCH is returned.  That is interpreted
	as an error, and halt/reboot exits.  It does this all after having
	disabled init, and so the system hangs.

>How-To-Repeat:
	Boot single-user.  enter 'exec reboot' or 'exec halt'.  Note the:

		SIGTERM processes: No such process

	error message, and that the system is then dead.

>Fix:
	A patch is included below, which:
		(1) ignores an ESRCH return in that particular case, and
		(2) for other error returns, re-enables init before
		    exiting.

*** reboot.c.old	Thu Jul 11 14:43:02 1996
--- reboot.c	Thu Jul 11 15:18:05 1996
***************
*** 140,147 ****
  	(void)signal(SIGHUP, SIG_IGN);
  
  	/* Send a SIGTERM first, a chance to save the buffers. */
! 	if (kill(-1, SIGTERM) == -1)
! 		err("SIGTERM processes: %s", strerror(errno));
  
  	/*
  	 * After the processes receive the signal, start the rest of the
--- 140,157 ----
  	(void)signal(SIGHUP, SIG_IGN);
  
  	/* Send a SIGTERM first, a chance to save the buffers. */
! 	if (kill(-1, SIGTERM) == -1) {
! 		/*
! 		 * If ESRCH, everything's OK: we're the only non-system
! 		 * process!  That can happen e.g. via 'exec reboot' in
! 		 * single-user mode.
! 		 */
! 		if (errno != ESRCH) {
! 			(void)fprintf(stderr, "%s: SIGTERM processes: %s",
! 			    dohalt ? "halt" : "reboot", strerror(errno));
! 			goto restart;
! 		}
! 	}
  
  	/*
  	 * After the processes receive the signal, start the rest of the
>Audit-Trail:
>Unformatted: