Revision: 23051 http://trac.macosforge.org/projects/launchd/changeset/23051 Author: zarzycki@apple.com Date: 2007-02-09 09:56:21 -0800 (Fri, 09 Feb 2007) Log Message: ----------- Better shutdown debugging. Modified Paths: -------------- trunk/launchd/src/launchd.c trunk/launchd/src/launchd.h trunk/launchd/src/launchd_core_logic.c Modified: trunk/launchd/src/launchd.c =================================================================== --- trunk/launchd/src/launchd.c 2007-02-09 01:51:31 UTC (rev 23050) +++ trunk/launchd/src/launchd.c 2007-02-09 17:56:21 UTC (rev 23051) @@ -394,28 +394,26 @@ void launchd_shutdown(void) { + struct stat sb; + if (shutdown_in_progress) { return; } shutdown_in_progress = true; -#if 0 - struct stat sb; + if (getpid() == 1) { + if (stat("/var/db/debugShutdownHangs", &sb) != -1) { + /* + * When this changes to a more sustainable API, update this: + * http://howto.apple.com/db.cgi?Debugging_Apps_Non-Responsive_At_Shutdown + */ + debug_shutdown_hangs = true; + } - if (stat("/var/db/debugShutdownHangs", &sb) != -1) { - /* - * When this changes to a more sustainable API, update this: - * http://howto.apple.com/db.cgi?Debugging_Apps_Non-Responsive_At_Shutdown - */ - debug_shutdown_hangs = true; - } -#else - if (getpid() == 1) { launchd_assumes(kevent_mod((uintptr_t)debugshutdown_callback, EVFILT_TIMER, EV_ADD|EV_ONESHOT, NOTE_SECONDS, 5, &kqdebugshutdown_callback) != -1); } -#endif rlcj = NULL; @@ -654,6 +652,9 @@ pid_t sddp; if (launchd_assumes(posix_spawn(&sddp, sdd_args[0], NULL, NULL, sdd_args, environ) == 0)) { - launchd_assumes(kevent_mod(sddp, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, &kqsimple_zombie_reaper) != -1); + int wstatus; + + /* No bootstrap port was given. It is safe to block. */ + launchd_assumes(waitpid(sddp, &wstatus, 0) != -1); } } Modified: trunk/launchd/src/launchd.h =================================================================== --- trunk/launchd/src/launchd.h 2007-02-09 01:51:31 UTC (rev 23050) +++ trunk/launchd/src/launchd.h 2007-02-09 17:56:21 UTC (rev 23051) @@ -31,7 +31,6 @@ struct kevent; struct conncb; -extern kq_callback kqsimple_zombie_reaper; extern sigset_t blocked_signals; extern bool debug_shutdown_hangs; extern bool network_up; Modified: trunk/launchd/src/launchd_core_logic.c =================================================================== --- trunk/launchd/src/launchd_core_logic.c 2007-02-09 01:51:31 UTC (rev 23050) +++ trunk/launchd/src/launchd_core_logic.c 2007-02-09 17:56:21 UTC (rev 23051) @@ -337,22 +337,12 @@ static bool cronemu_hour(struct tm *wtm, int hour, int min); static bool cronemu_min(struct tm *wtm, int min); -static void simple_zombie_reaper(void *, struct kevent *); - -kq_callback kqsimple_zombie_reaper = simple_zombie_reaper; - static int dir_has_files(job_t j, const char *path); static char **mach_cmd2argv(const char *string); jobmgr_t root_jobmgr; jobmgr_t gc_this_jobmgr; void -simple_zombie_reaper(void *obj __attribute__((unused)), struct kevent *kev) -{ - waitpid(kev->ident, NULL, 0); -} - -void job_ignore(job_t j) { struct semaphoreitem *si; @@ -1779,9 +1769,7 @@ if ((uintptr_t)j == kev->ident || (uintptr_t)&j->start_interval == kev->ident) { job_dispatch(j, true); } else if ((uintptr_t)&j->exit_timeout == kev->ident) { - if (debug_shutdown_hangs) { - job_force_sampletool(j); - } + job_force_sampletool(j); job_log(j, LOG_WARNING, "Exit timeout elapsed (%u seconds). Killing.", j->exit_timeout); job_assumes(j, kill(j->p, SIGKILL) != -1); } else { @@ -3625,16 +3613,72 @@ void job_force_sampletool(job_t j) { - char *sample_args[] = { "sample", NULL, "1", "-mayDie", NULL }; + struct stat sb; + char logfile[PATH_MAX]; char pidstr[100]; + char *sample_args[] = { "sample", pidstr, "1", "-mayDie", "-file", logfile, NULL }; + char *contents = NULL; + int logfile_fd = -1; + int console_fd = -1; pid_t sp; + + if (!debug_shutdown_hangs) { + return; + } snprintf(pidstr, sizeof(pidstr), "%u", j->p); - sample_args[1] = pidstr; + snprintf(logfile, sizeof(logfile), "/var/log/shutdown/%s-%u.sample.txt", j->label, j->p); - if (job_assumes(j, posix_spawnp(&sp, sample_args[0], NULL, NULL, sample_args, environ) == 0)) { - job_assumes(j, kevent_mod(sp, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, &kqsimple_zombie_reaper) != -1); + job_assumes(j, mkdir("/var/log/shutdown", S_IRWXU) != -1 || errno == EEXIST); + + /* + * This will stall launchd for as long as the 'sample' tool runs. + * + * We didn't give the 'sample' tool a bootstrap port, so it therefore + * can't deadlock against launchd. + */ + if (job_assumes(j, (errno = posix_spawnp(&sp, sample_args[0], NULL, NULL, sample_args, environ)) == 0)) { + int wstatus; + + job_assumes(j, waitpid(sp, &wstatus, 0) != -1); } + + if (!job_assumes(j, (logfile_fd = open(logfile, O_RDONLY|O_NOCTTY)) != -1)) { + goto out; + } + + if (!job_assumes(j, (console_fd = open(_PATH_CONSOLE, O_WRONLY|O_APPEND||O_NOCTTY)) != -1)) { + goto out; + } + + if (!job_assumes(j, fstat(logfile_fd, &sb) != -1)) { + goto out; + } + + contents = malloc(sb.st_size); + + if (!job_assumes(j, contents != NULL)) { + goto out; + } + + if (!job_assumes(j, read(logfile_fd, contents, sb.st_size) == sb.st_size)) { + goto out; + } + + job_assumes(j, write(console_fd, contents, sb.st_size) == sb.st_size); + +out: + if (contents) { + free(contents); + } + + if (logfile_fd != -1) { + job_assumes(j, close(logfile_fd) != -1); + } + + if (console_fd != -1) { + job_assumes(j, close(console_fd) != -1); + } } bool
participants (1)
-
source_changes@macosforge.org