[launchd-changes] [23867] trunk/launchd/src

source_changes at macosforge.org source_changes at macosforge.org
Tue Mar 24 15:27:19 PDT 2009


Revision: 23867
          http://trac.macosforge.org/projects/launchd/changeset/23867
Author:   dsorresso at apple.com
Date:     2009-03-24 15:27:19 -0700 (Tue, 24 Mar 2009)
Log Message:
-----------
Added code for debugging system bootstrapper crashes.

Modified Paths:
--------------
    trunk/launchd/src/launchctl.c
    trunk/launchd/src/launchd_core_logic.c

Modified: trunk/launchd/src/launchctl.c
===================================================================
--- trunk/launchd/src/launchctl.c	2009-03-24 20:59:07 UTC (rev 23866)
+++ trunk/launchd/src/launchctl.c	2009-03-24 22:27:19 UTC (rev 23867)
@@ -170,6 +170,8 @@
 static void do_bootroot_magic(void);
 static void do_single_user_mode(bool);
 static bool do_single_user_mode2(void);
+static void do_crash_debug_mode(void);
+static bool do_crash_debug_mode2(void);
 static void read_launchd_conf(void);
 static void read_environment_dot_plist(void);
 static bool job_disabled_logic(launch_data_t obj);
@@ -177,6 +179,8 @@
 static void do_file_init(void) __attribute__((constructor));
 static void setup_system_context(void);
 static void tell_launchd_about_boot_args(void);
+static void handle_system_bootstrapper_crashes_separately(void);
+static void fatal_signal_handler(int sig, siginfo_t *si, void *uap);
 
 typedef enum {
 	BOOTCACHE_START = 1,
@@ -262,6 +266,7 @@
 static bool bootstrapping_system;
 static bool bootstrapping_peruser;
 static bool g_shutdown_debugging = false;
+static bool g_booting_verbose = false;
 
 static bool g_job_overrides_db_has_changed = false;
 static CFMutableDictionaryRef g_job_overrides_db = NULL;
@@ -1789,6 +1794,10 @@
 	if (!assumes(login_tty(fd) != -1)) {
 		_exit(EXIT_FAILURE);
 	}
+	
+	mach_timespec_t wt = { 5, 0 };
+	IOKitWaitQuiet(kIOMasterPortDefault, &wt); /* This will hopefully return after all the kexts have shut up. */
+	
 	setenv("TERM", "vt100", 1);
 	if (runcom_fsck) {
 		fprintf(stdout, "Singleuser boot -- fsck not done\n");
@@ -1805,6 +1814,64 @@
 	_exit(EXIT_FAILURE);
 }
 
+void
+do_crash_debug_mode(void)
+{
+	while (!do_crash_debug_mode2()) {
+		sleep(1);
+	}
+}
+
+bool
+do_crash_debug_mode2(void)
+{
+	int wstatus;
+	int fd;
+	pid_t p;
+	
+	switch ((p = fork())) {
+		case -1:
+			syslog(LOG_ERR, "can't fork crash debug shell, trying again: %m");
+			return false;
+		case 0:
+			break;
+		default:
+			assumes(waitpid(p, &wstatus, 0) != -1);
+			if (WIFEXITED(wstatus)) {
+				if (WEXITSTATUS(wstatus) == EXIT_SUCCESS) {
+					return true;
+				} else {
+					fprintf(stdout, "crash debug mode: exit status: %d\n", WEXITSTATUS(wstatus));
+				}
+			} else {
+				fprintf(stdout, "crash debug mode shell: %s\n", strsignal(WTERMSIG(wstatus)));
+			}
+			return false;
+	}
+	
+	revoke(_PATH_CONSOLE);
+	if (!assumes((fd = open(_PATH_CONSOLE, O_RDWR)) != -1)) {
+		_exit(EXIT_FAILURE);
+	}
+	if (!assumes(login_tty(fd) != -1)) {
+		_exit(EXIT_FAILURE);
+	}
+	
+	mach_timespec_t wt = { 5, 0 };
+	IOKitWaitQuiet(kIOMasterPortDefault, &wt); /* This will hopefully return after all the kexts have shut up. */
+	
+	setenv("TERM", "vt100", 1);
+	fprintf(stdout, "Entering boot-time debugging mode...\n");
+	fprintf(stdout, "The system bootstrapper process has crashed. To debug:\n");
+	fprintf(stdout, "\tgdb attach %i\n", getppid());
+	fprintf(stdout, "You can try booting the system with:\n");
+	fprintf(stdout, "\tlaunchctl load -S System -D All\n\n");
+	
+	execl(_PATH_BSHELL, "-sh", NULL);
+	syslog(LOG_ERR, "can't exec %s for crash debug: %m", _PATH_BSHELL);
+	_exit(EXIT_FAILURE);
+}
+
 static void
 exit_at_sigterm(int sig)
 {
@@ -1813,6 +1880,33 @@
 	}
 }
 
+void
+fatal_signal_handler(int sig __attribute__((unused)), siginfo_t *si __attribute__((unused)), void *uap __attribute__((unused)))
+{
+	do_crash_debug_mode();
+}
+
+void
+handle_system_bootstrapper_crashes_separately(void)
+{
+	if( !g_booting_verbose ) {
+		return;
+	}
+	
+	struct sigaction fsa;
+	
+	fsa.sa_sigaction = fatal_signal_handler;
+	fsa.sa_flags = SA_SIGINFO;
+	sigemptyset(&fsa.sa_mask);
+	
+	assumes(sigaction(SIGILL, &fsa, NULL) != -1);
+	assumes(sigaction(SIGFPE, &fsa, NULL) != -1);
+	assumes(sigaction(SIGBUS, &fsa, NULL) != -1);
+	assumes(sigaction(SIGSEGV, &fsa, NULL) != -1);
+	assumes(sigaction(SIGTRAP, &fsa, NULL) != -1);
+	assumes(sigaction(SIGABRT, &fsa, NULL) != -1);
+}
+
 static void
 system_specific_bootstrap(bool sflag)
 {
@@ -1879,6 +1973,7 @@
 
 	tell_launchd_about_boot_args();
 	read_launchd_conf();
+	handle_system_bootstrapper_crashes_separately();
 
 	if (path_check("/var/account/acct")) {
 		assumes(acct("/var/account/acct") != -1);
@@ -3012,7 +3107,6 @@
 		IOObjectRelease(entry);
 	} while( 0 );
 	
-	Boolean is_verbose = false;
 	if( value ) {
 		/* Normally I'd just use CFStringFind(), but the compiler whines about it returning a 
 		 * struct with -Wall.
@@ -3020,10 +3114,10 @@
 		CFRange range = { 0, CFStringGetLength(value) };
 		CFRange found_range = { 0, 0 };
 		
-		is_verbose = CFStringFindWithOptions(value, CFSTR("-v"), range, 0, &found_range);
+		g_booting_verbose = CFStringFindWithOptions(value, CFSTR("-v"), range, 0, &found_range);
 		CFRelease(value);
 				
-		assumes(vproc_swap_integer(NULL, VPROC_GSK_SHUTDOWN_DEBUGGING, (int64_t *)&is_verbose, NULL) == KERN_SUCCESS);
+		assumes(vproc_swap_integer(NULL, VPROC_GSK_SHUTDOWN_DEBUGGING, (int64_t *)&g_booting_verbose, NULL) == KERN_SUCCESS);
 	}
 }
 

Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c	2009-03-24 20:59:07 UTC (rev 23866)
+++ trunk/launchd/src/launchd_core_logic.c	2009-03-24 22:27:19 UTC (rev 23867)
@@ -2515,6 +2515,8 @@
 	struct rusage ru;
 	int status;
 
+	bool is_system_bootstrapper = j->is_bootstrapper && pid1_magic && !j->mgr->parentmgr;
+	
 	job_log(j, LOG_DEBUG, "Reaping");
 
 	if (j->shmem) {
@@ -2561,7 +2563,7 @@
 #endif
 			}
 		}
-
+		
 		/*
 		 * 5020256
 		 *
@@ -2655,6 +2657,10 @@
 					job_log(j, LOG_WARNING, "Exited abnormally: %s", strsignal(s));
 					break;
 			}
+			
+			if( is_system_bootstrapper && j->crashed ) {
+				job_log(j, LOG_ERR | LOG_CONSOLE, "The %s bootstrapper has crashed: %s", j->mgr->name, strsignal(s));
+			}
 		}
 	}
 
@@ -2804,9 +2810,6 @@
 	switch( (p = fork()) ) {
 		case 0	:
 			job_assumes(j, runtime_close(execpair[0]) != -1);
-			/* Handle exceptions directly. */
-			task_set_exception_ports(mach_task_self(), EXC_MASK_CRASH, runtime_get_kernel_port(), EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, f);
-			
 			/* Wait for the parent to attach a kevent. */
 			read(_fd(execpair[1]), &p, sizeof(p));
 			what_to_do(j);
@@ -6863,6 +6866,8 @@
 			goto out_bad;
 		}
 		
+		job_log(j, LOG_DEBUG | LOG_CONSOLE, "Location of job cache database: %s", launch_data_get_string(output_obj));
+			
 		launch_data_free(output_obj);
 		break;
 	case 0:
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/launchd-changes/attachments/20090324/f651f22b/attachment.html>


More information about the launchd-changes mailing list