Revision: 23304 http://trac.macosforge.org/projects/launchd/changeset/23304 Author: zarzycki@apple.com Date: 2007-07-11 15:11:37 -0700 (Wed, 11 Jul 2007) Log Message: ----------- <rdar://problem/5194957> launchctl unload should block until unload is complete Modified Paths: -------------- trunk/launchd/src/launchctl.c trunk/launchd/src/launchd_core_logic.c trunk/launchd/src/libvproc_private.h trunk/launchd/src/protocol_job.defs trunk/launchd/src/protocol_job_reply.defs Modified: trunk/launchd/src/launchctl.c =================================================================== --- trunk/launchd/src/launchctl.c 2007-07-11 18:10:33 UTC (rev 23303) +++ trunk/launchd/src/launchctl.c 2007-07-11 22:11:37 UTC (rev 23304) @@ -440,11 +440,8 @@ void unloadjob(launch_data_t job) { - launch_data_t resp, tmp, tmps, msg; - int e; + launch_data_t tmps; - msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY); - tmp = launch_data_alloc(LAUNCH_DATA_STRING); tmps = launch_data_dict_lookup(job, LAUNCH_JOBKEY_LABEL); if (!tmps) { @@ -452,20 +449,7 @@ return; } - launch_data_set_string(tmp, launch_data_get_string(tmps)); - launch_data_dict_insert(msg, tmp, LAUNCH_KEY_REMOVEJOB); - resp = launch_msg(msg); - launch_data_free(msg); - if (!resp) { - fprintf(stderr, "%s: Error: launch_msg(): %s\n", getprogname(), strerror(errno)); - return; - } - if (LAUNCH_DATA_ERRNO == launch_data_get_type(resp)) { - if ((e = launch_data_get_errno(resp))) { - fprintf(stderr, "%s\n", strerror(e)); - } - } - launch_data_free(resp); + assumes(_vproc_send_signal_by_label(launch_data_get_string(tmps), VPROC_MAGIC_UNLOAD_SIGNAL) == NULL); } launch_data_t Modified: trunk/launchd/src/launchd_core_logic.c =================================================================== --- trunk/launchd/src/launchd_core_logic.c 2007-07-11 18:10:33 UTC (rev 23303) +++ trunk/launchd/src/launchd_core_logic.c 2007-07-11 22:11:37 UTC (rev 23304) @@ -105,8 +105,14 @@ extern char **environ; -mach_port_t inherited_bootstrap_port; +struct waiting_for_removal { + SLIST_ENTRY(waiting_for_removal) sle; + mach_port_t reply_port; +}; +static bool waiting4removal_new(job_t j, mach_port_t rp); +static void waiting4removal_delete(job_t j, struct waiting_for_removal *w4r); + struct mspolicy { SLIST_ENTRY(mspolicy) sle; unsigned int allow:1, per_pid:1; @@ -308,6 +314,7 @@ SLIST_HEAD(, mspolicy) mspolicies; SLIST_HEAD(, machservice) machservices; SLIST_HEAD(, semaphoreitem) semaphores; + SLIST_HEAD(, waiting_for_removal) removal_watchers; #if DO_RUSAGE_SUMMATION struct rusage ru; #endif @@ -447,6 +454,7 @@ static jobmgr_t background_jobmgr; /* process wide globals */ +mach_port_t inherited_bootstrap_port; jobmgr_t root_jobmgr; void @@ -711,6 +719,7 @@ void job_remove(job_t j) { + struct waiting_for_removal *w4r; struct calendarinterval *ci; struct semaphoreitem *si; struct socketgroup *sg; @@ -778,6 +787,9 @@ while ((si = SLIST_FIRST(&j->semaphores))) { semaphoreitem_delete(j, si); } + while ((w4r = SLIST_FIRST(&j->removal_watchers))) { + waiting4removal_delete(j, w4r); + } if (j->prog) { free(j->prog); @@ -4769,7 +4781,7 @@ } kern_return_t -job_mig_send_signal(job_t j, name_t targetlabel, int sig) +job_mig_send_signal(job_t j, mach_port_t srp, name_t targetlabel, int sig) { struct ldcred ldc; job_t otherj; @@ -4788,7 +4800,24 @@ return BOOTSTRAP_UNKNOWN_SERVICE; } - if (otherj->p) { + if (sig == VPROC_MAGIC_UNLOAD_SIGNAL) { + bool do_block = otherj->p; + + if (otherj->anonymous) { + return BOOTSTRAP_NOT_PRIVILEGED; + } + + job_remove(otherj); + + if (do_block) { + job_log(j, LOG_DEBUG, "Blocking MIG return of job_remove(): %s", otherj->label); + /* this is messy. We shouldn't access 'otherj' after job_remove(), but we check otherj->p first... */ + job_assumes(otherj, waiting4removal_new(otherj, srp)); + return MIG_NO_REPLY; + } else { + return 0; + } + } else if (otherj->p) { job_assumes(j, kill(otherj->p, sig) != -1); } @@ -6134,3 +6163,29 @@ free(msp); } + +bool +waiting4removal_new(job_t j, mach_port_t rp) +{ + struct waiting_for_removal *w4r; + + if (!job_assumes(j, (w4r = malloc(sizeof(struct waiting_for_removal))) != NULL)) { + return false; + } + + w4r->reply_port = rp; + + SLIST_INSERT_HEAD(&j->removal_watchers, w4r, sle); + + return true; +} + +void +waiting4removal_delete(job_t j, struct waiting_for_removal *w4r) +{ + job_assumes(j, job_mig_send_signal_reply(w4r->reply_port, 0) == 0); + + SLIST_REMOVE(&j->removal_watchers, w4r, waiting_for_removal, sle); + + free(w4r); +} Modified: trunk/launchd/src/libvproc_private.h =================================================================== --- trunk/launchd/src/libvproc_private.h 2007-07-11 18:10:33 UTC (rev 23303) +++ trunk/launchd/src/libvproc_private.h 2007-07-11 22:11:37 UTC (rev 23304) @@ -31,6 +31,9 @@ #pragma GCC visibility push(default) +/* DO NOT use this. This is a hack for launchctl */ +#define VPROC_MAGIC_UNLOAD_SIGNAL 0x4141504C + typedef enum { VPROC_GSK_LAST_EXIT_STATUS = 1, VPROC_GSK_GLOBAL_ON_DEMAND, Modified: trunk/launchd/src/protocol_job.defs =================================================================== --- trunk/launchd/src/protocol_job.defs 2007-07-11 18:10:33 UTC (rev 23303) +++ trunk/launchd/src/protocol_job.defs 2007-07-11 22:11:37 UTC (rev 23304) @@ -70,6 +70,7 @@ routine send_signal( __bs_port : job_t; + sreplyport __rport : mach_port_make_send_once_t; __label : name_t; __signal : integer_t); Modified: trunk/launchd/src/protocol_job_reply.defs =================================================================== --- trunk/launchd/src/protocol_job_reply.defs 2007-07-11 18:10:33 UTC (rev 23303) +++ trunk/launchd/src/protocol_job_reply.defs 2007-07-11 22:11:37 UTC (rev 23304) @@ -37,7 +37,9 @@ skip; /* look_up */ -skip; /* send_signal */ +simpleroutine job_mig_send_signal_reply( + __r_port : mach_port_move_send_once_t; + __result : kern_return_t, RetCode); skip; /* parent */
participants (1)
-
source_changes@macosforge.org