+do_pid1_crash_diagnosis_mode(const char *msg)
+{
+ if (g_wsp) {
+ kill(g_wsp, SIGKILL);
+ sleep(3);
+ g_wsp = 0;
+ }
+
+ while (g_shutdown_debugging && !do_pid1_crash_diagnosis_mode2(msg)) {
+ sleep(1);
+ }
+}
+
+int
+basic_fork(void)
+{
+ int wstatus = 0;
+ pid_t p;
+
+ switch ((p = fork())) {
+ case -1:
+ runtime_syslog(LOG_ERR | LOG_CONSOLE, "Can't fork PID 1 copy for crash debugging: %m");
+ return p;
+ case 0:
+ return p;
+ default:
+ do {
+ (void)waitpid(p, &wstatus, 0);
+ } while(!WIFEXITED(wstatus));
+
+ fprintf(stdout, "PID 1 copy: exit status: %d\n", WEXITSTATUS(wstatus));
+
+ return 1;
+ }
+
+ return -1;
+}
+
+bool
+do_pid1_crash_diagnosis_mode2(const char *msg)
+{
+ if (basic_fork() == 0) {
+ /* Neuter our bootstrap port so that the shell doesn't try talking to us while
+ * we're blocked waiting on it.
+ */
+ if (g_console) {
+ fflush(g_console);
+ }
+ task_set_bootstrap_port(mach_task_self(), MACH_PORT_NULL);
+ if (basic_fork() != 0) {
+ if (g_console) {
+ fflush(g_console);
+ }
+ return true;
+ }
+ } else {
+ return true;
+ }
+
+ int fd;
+ revoke(_PATH_CONSOLE);
+ if ((fd = open(_PATH_CONSOLE, O_RDWR)) == -1) {
+ _exit(2);
+ }
+ if (login_tty(fd) == -1) {
+ _exit(3);
+ }
+ setenv("TERM", "vt100", 1);
+ fprintf(stdout, "\n");
+ fprintf(stdout, "Entering launchd PID 1 debugging mode...\n");
+ fprintf(stdout, "The PID 1 launchd has crashed %s.\n", msg);
+ fprintf(stdout, "It has fork(2)ed itself for debugging.\n");
+ fprintf(stdout, "To debug the crashing thread of PID 1:\n");
+ fprintf(stdout, " gdb attach %d\n", getppid());
+ fprintf(stdout, "To exit this shell and shut down:\n");
+ fprintf(stdout, " kill -9 1\n");
+ fprintf(stdout, "A sample of PID 1 has been written to %s\n", PID1_CRASH_LOGFILE);
+ fprintf(stdout, "\n");
+ fflush(stdout);
+
+ execl(_PATH_BSHELL, "-sh", NULL);
+ syslog(LOG_ERR, "can't exec %s for PID 1 crash debugging: %m", _PATH_BSHELL);
+ _exit(EXIT_FAILURE);
+}
+
+void
+fatal_signal_handler(int sig, siginfo_t *si, void *uap __attribute__((unused)))