Modified: trunk/launchd/src/launchd.c (23041 => 23042)
--- 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_core_logic.c (23041 => 23042)
--- 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) {