Revision: 23042 http://trac.macosforge.org/projects/launchd/changeset/23042 Author: zarzycki@apple.com Date: 2007-02-08 07:21:26 -0800 (Thu, 08 Feb 2007) Log Message: ----------- <rdar://problem/4943031> Add plist option to mimic the kernel's KERN_PROCDELAYTERM Modified Paths: -------------- trunk/launchd/src/launchd.c trunk/launchd/src/launchd.h trunk/launchd/src/launchd.plist.5 trunk/launchd/src/launchd_core_logic.c trunk/launchd/src/launchd_core_logic.h trunk/launchd/src/liblaunch_public.h Modified: trunk/launchd/src/launchd.c =================================================================== --- trunk/launchd/src/launchd.c 2007-02-08 01:28:03 UTC (rev 23041) +++ trunk/launchd/src/launchd.c 2007-02-08 15:21:26 UTC (rev 23042) @@ -110,7 +110,7 @@ static const char *launchctl_bootstrap_tool[] = { "/bin/launchctl", /* "bootstrap", */ NULL }; sigset_t blocked_signals = 0; -bool shutdown_in_progress = false; +static bool shutdown_in_progress = false; bool debug_shutdown_hangs = false; bool network_up = false; int batch_disabler_count = 0; @@ -469,7 +469,7 @@ rlcj = NULL; - jobmgr_remove_all_inactive(root_jobmgr); + root_jobmgr = jobmgr_shutdown(root_jobmgr); } void @@ -676,7 +676,7 @@ void launchd_post_kevent(void) { - if (shutdown_in_progress && jobmgr_is_idle(root_jobmgr)) { + if (shutdown_in_progress && (!root_jobmgr || jobmgr_is_idle(root_jobmgr))) { shutdown_in_progress = false; if (getpid() == 1) { Modified: trunk/launchd/src/launchd.h =================================================================== --- trunk/launchd/src/launchd.h 2007-02-08 01:28:03 UTC (rev 23041) +++ trunk/launchd/src/launchd.h 2007-02-08 15:21:26 UTC (rev 23042) @@ -34,7 +34,6 @@ extern kq_callback kqsimple_zombie_reaper; extern sigset_t blocked_signals; -extern bool shutdown_in_progress; extern bool debug_shutdown_hangs; extern bool network_up; extern int batch_disabler_count; Modified: trunk/launchd/src/launchd.plist.5 =================================================================== --- trunk/launchd/src/launchd.plist.5 2007-02-08 01:28:03 UTC (rev 23041) +++ trunk/launchd/src/launchd.plist.5 2007-02-08 15:21:26 UTC (rev 23042) @@ -271,6 +271,12 @@ This optional key specifies what .Xr nice 3 value should be applied to the daemon. +.It Sy HopefullyExitsLast <boolean> +This optional key causes programs to exit in a second wave during system +shutdown. This key exists because some jobs don't reference count their +clients, and therefore do not know when it is safe to exit. The use of this key +should be considered a temporary solution until the software can be changed to +properly reference count clients. .It Sy LowPriorityIO <boolean> This optional key specifies whether the kernel should consider this daemon to be low priority when doing file system I/O. .It Sy LaunchOnlyOnce <boolean> Modified: trunk/launchd/src/launchd_core_logic.c =================================================================== --- trunk/launchd/src/launchd_core_logic.c 2007-02-08 01:28:03 UTC (rev 23041) +++ trunk/launchd/src/launchd_core_logic.c 2007-02-08 15:21:26 UTC (rev 23042) @@ -199,7 +199,7 @@ char *jm_stdout; char *jm_stderr; unsigned int global_on_demand_cnt; - unsigned int transfer_bstrap:1; + unsigned int transfer_bstrap:1, sent_stop_to_hopeful_jobs:1, shutting_down:1; char name[0]; }; @@ -208,6 +208,7 @@ static jobmgr_t jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t checkin_port); static jobmgr_t jobmgr_parent(jobmgr_t jm); +static jobmgr_t jobmgr_tickle(jobmgr_t jm); static void jobmgr_dispatch_all(jobmgr_t jm); static job_t jobmgr_new_anonymous(jobmgr_t jm); static job_t job_mig_intran2(jobmgr_t jm, mach_port_t p); @@ -268,7 +269,7 @@ anonymous:1; mode_t mask; unsigned int globargv:1, wait4debugger:1, unload_at_exit:1, stall_before_exec:1, only_once:1, - currently_ignored:1, forced_peers_to_demand_mode:1, setnice:1; + currently_ignored:1, forced_peers_to_demand_mode:1, setnice:1, hopefully_exits_last:1; char label[0]; }; @@ -510,23 +511,27 @@ return r; } -void -jobmgr_remove_all_inactive(jobmgr_t jm) +jobmgr_t +jobmgr_shutdown(jobmgr_t jm) { jobmgr_t jmi, jmn; job_t ji, jn; SLIST_FOREACH_SAFE(jmi, &jm->submgrs, sle, jmn) { - jobmgr_remove_all_inactive(jmi); + jobmgr_shutdown(jmi); } SLIST_FOREACH_SAFE(ji, &jm->jobs, sle, jn) { if (!job_active(ji)) { job_remove(ji); - } else { + } else if (!ji->hopefully_exits_last) { job_stop(ji); } } + + jm->shutting_down = true; + + return jobmgr_tickle(jm); } void @@ -595,10 +600,6 @@ } } - if (job_assumes(j, j->mgr)) { - SLIST_REMOVE(&j->mgr->jobs, j, job_s, sle); - } - if (j->forkfd) { job_assumes(j, close(j->forkfd) != -1); } @@ -672,6 +673,12 @@ } kevent_mod((uintptr_t)j, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + + if (job_assumes(j, j->mgr)) { + SLIST_REMOVE(&j->mgr->jobs, j, job_s, sle); + jobmgr_tickle(j->mgr); + } + free(j); } @@ -894,7 +901,7 @@ int i, cc = 0; job_t j; - if (shutdown_in_progress) { + if (jm->shutting_down) { errno = EINVAL; return NULL; } @@ -1036,6 +1043,12 @@ j->debug = value; } break; + case 'h': + case 'H': + if (strcasecmp(key, LAUNCH_JOBKEY_HOPEFULLYEXITSLAST) == 0) { + j->hopefully_exits_last = value; + } + break; case 's': case 'S': if (strcasecmp(key, LAUNCH_JOBKEY_SESSIONCREATE) == 0) { @@ -2805,7 +2818,7 @@ } job_log(j, LOG_INFO, "Exited. Was only configured to run once."); return true; - } else if (shutdown_in_progress) { + } else if (j->mgr->shutting_down) { job_log(j, LOG_INFO, "Exited while shutdown in progress."); return true; } else if (!j->checkedin && (!SLIST_EMPTY(&j->sockets) || !SLIST_EMPTY(&j->machservices))) { @@ -3162,6 +3175,35 @@ } } +jobmgr_t +jobmgr_tickle(jobmgr_t jm) +{ + job_t ji; + + if (jm->sent_stop_to_hopeful_jobs || !jm->shutting_down) { + return jm; + } + + SLIST_FOREACH(ji, &jm->jobs, sle) { + if (ji->p && !ji->hopefully_exits_last) { + return jm; + } + } + + SLIST_FOREACH(ji, &jm->jobs, sle) { + job_stop(ji); + } + + jm->sent_stop_to_hopeful_jobs = true; + + if (jobmgr_is_idle(jm)) { + jobmgr_remove(jm); + return NULL; + } + + return jm; +} + bool jobmgr_is_idle(jobmgr_t jm) { @@ -3321,11 +3363,7 @@ */ if (jm->req_port == port) { - if (jm == root_jobmgr) { - launchd_shutdown(); - } else { - return jobmgr_remove(jm); - } + jobmgr_shutdown(jm); } SLIST_FOREACH_SAFE(jmi, &jm->submgrs, sle, jmn) { Modified: trunk/launchd/src/launchd_core_logic.h =================================================================== --- trunk/launchd/src/launchd_core_logic.h 2007-02-08 01:28:03 UTC (rev 23041) +++ trunk/launchd/src/launchd_core_logic.h 2007-02-08 15:21:26 UTC (rev 23042) @@ -32,7 +32,7 @@ void jobmgr_set_stdout(jobmgr_t jm, const char *what); void jobmgr_set_stderr(jobmgr_t jm, const char *what); bool jobmgr_is_idle(jobmgr_t jm); -void jobmgr_remove_all_inactive(jobmgr_t jm); +jobmgr_t jobmgr_shutdown(jobmgr_t jm); void jobmgr_dispatch_all_semaphores(jobmgr_t jm); job_t jobmgr_find(jobmgr_t jm, const char *label); void jobmgr_delete_anything_with_port(jobmgr_t jm, mach_port_t port); Modified: trunk/launchd/src/liblaunch_public.h =================================================================== --- trunk/launchd/src/liblaunch_public.h 2007-02-08 01:28:03 UTC (rev 23041) +++ trunk/launchd/src/liblaunch_public.h 2007-02-08 15:21:26 UTC (rev 23042) @@ -78,6 +78,7 @@ #define LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES "UserEnvironmentVariables" #define LAUNCH_JOBKEY_UMASK "Umask" #define LAUNCH_JOBKEY_NICE "Nice" +#define LAUNCH_JOBKEY_HOPEFULLYEXITSLAST "HopefullyExitsLast" #define LAUNCH_JOBKEY_LOWPRIORITYIO "LowPriorityIO" #define LAUNCH_JOBKEY_SESSIONCREATE "SessionCreate" #define LAUNCH_JOBKEY_SOFTRESOURCELIMITS "SoftResourceLimits"
participants (1)
-
source_changes@macosforge.org