Revision: 23889 http://trac.macosforge.org/projects/launchd/changeset/23889 Author: dsorresso@apple.com Date: 2009-04-09 18:56:53 -0700 (Thu, 09 Apr 2009) Log Message: ----------- <rdar://problem/6754652> Tweak per-user suspend and resume Modified Paths: -------------- trunk/launchd/src/launchd_core_logic.c trunk/launchd/src/libvproc.c Modified: trunk/launchd/src/launchd_core_logic.c =================================================================== --- trunk/launchd/src/launchd_core_logic.c 2009-04-09 18:05:32 UTC (rev 23888) +++ trunk/launchd/src/launchd_core_logic.c 2009-04-10 01:56:53 UTC (rev 23889) @@ -399,6 +399,11 @@ #define AUTO_PICK_LEGACY_LABEL (const char *)(~0) #define AUTO_PICK_ANONYMOUS_LABEL (const char *)(~1) +struct suspended_peruser { + LIST_ENTRY(suspended_peruser) sle; + job_t j; +}; + struct job_s { kq_callback kqjob_callback; /* MUST be first element of this structure for benefit of launchd's run loop. */ LIST_ENTRY(job_s) sle; @@ -407,10 +412,9 @@ LIST_ENTRY(job_s) pid_hash_sle; LIST_ENTRY(job_s) label_hash_sle; LIST_ENTRY(job_s) global_env_sle; - LIST_ENTRY(job_s) suspended_peruser_sle; STAILQ_ENTRY(job_s) pending_samples_sle; SLIST_ENTRY(job_s) curious_jobs_sle; - LIST_HEAD(, job_s) suspended_perusers; + LIST_HEAD(, suspended_peruser) suspended_perusers; LIST_HEAD(, waiting_for_exit) exit_watchers; SLIST_HEAD(, socketgroup) sockets; SLIST_HEAD(, calendarinterval) cal_intervals; @@ -2732,14 +2736,15 @@ } } - job_t ji = NULL; - while( (ji = LIST_FIRST(&j->suspended_perusers)) ) { - job_log(j, LOG_ERR, "Job exited before resuming per-user launchd for UID %u. Will forcibly resume.", ji->mach_uid); - ji->peruser_suspend_count--; - if( ji->peruser_suspend_count == 0 ) { - LIST_REMOVE(ji, suspended_peruser_sle); + struct suspended_peruser *spi = NULL; + while( (spi = LIST_FIRST(&j->suspended_perusers)) ) { + job_log(j, LOG_ERR, "Job exited before resuming per-user launchd for UID %u. Will forcibly resume.", spi->j->mach_uid); + spi->j->peruser_suspend_count--; + if( spi->j->peruser_suspend_count == 0 ) { + job_dispatch(spi->j, false); } - job_dispatch(ji, false); + LIST_REMOVE(spi, sle); + free(spi); } struct waiting_for_exit *w4e = NULL; @@ -7148,42 +7153,56 @@ } break; case VPROC_GSK_PERUSER_SUSPEND: - if( pid1_magic && ldc->euid == 0 ) { + if( job_assumes(j, pid1_magic && ldc->euid == 0) ) { mach_port_t junk = MACH_PORT_NULL; job_t jpu = jobmgr_lookup_per_user_context_internal(j, (uid_t)inval, false, &junk); - if( jpu ) { - job_t ji = NULL; - LIST_FOREACH( ji, &j->suspended_perusers, suspended_peruser_sle ) { - if( (int64_t)(ji->mach_uid) == inval ) { - job_log(j, LOG_WARNING, "Job tried to suspend per-user launchd for UID %u twice.", ji->mach_uid); + if( job_assumes(j, jpu != NULL) ) { + struct suspended_peruser *spi = NULL; + LIST_FOREACH( spi, &j->suspended_perusers, sle ) { + if( (int64_t)(spi->j->mach_uid) == inval ) { + job_log(j, LOG_WARNING, "Job tried to suspend per-user launchd for UID %lli twice.", inval); break; } } - - if( ji == NULL ) { - jpu->peruser_suspend_count++; - LIST_INSERT_HEAD(&j->suspended_perusers, jpu, suspended_peruser_sle); - job_stop(jpu); + + if( spi == NULL ) { + job_log(j, LOG_INFO, "Job is suspending the per-user launchd for UID %lli.", inval); + spi = (struct suspended_peruser *)calloc(sizeof(struct suspended_peruser), 1); + if( job_assumes(j, spi != NULL) ) { + spi->j = jpu; + spi->j->peruser_suspend_count++; + LIST_INSERT_HEAD(&j->suspended_perusers, spi, sle); + job_stop(spi->j); + } else { + kr = BOOTSTRAP_NO_MEMORY; + } } } + } else { + kr = 1; } break; case VPROC_GSK_PERUSER_RESUME: - if( pid1_magic && ldc->euid == 0 ) { - job_t ji = NULL, jt = NULL; - LIST_FOREACH_SAFE( ji, &j->suspended_perusers, suspended_peruser_sle, jt ) { - if( (int64_t)(ji->mach_uid) == inval ) { - ji->peruser_suspend_count--; - LIST_REMOVE(ji, suspended_peruser_sle); + if( job_assumes(j, pid1_magic == true) ) { + struct suspended_peruser *spi = NULL, *spt = NULL; + LIST_FOREACH_SAFE( spi, &j->suspended_perusers, sle, spt ) { + if( (int64_t)(spi->j->mach_uid) == inval ) { + spi->j->peruser_suspend_count--; + LIST_REMOVE(spi, sle); + job_log(j, LOG_INFO, "Job is resuming the per-user launchd for UID %lli.", inval); break; } } - if( ji == NULL ) { - job_log(j, LOG_WARNING, "Job tried to resume per-user launchd for UID %llu that it did not suspend.", inval); - } else if( ji->peruser_suspend_count == 0 ) { - job_dispatch(ji, false); + if( !job_assumes(j, spi != NULL) ) { + job_log(j, LOG_WARNING, "Job tried to resume per-user launchd for UID %lli that it did not suspend.", inval); + kr = BOOTSTRAP_NOT_PRIVILEGED; + } else if( spi->j->peruser_suspend_count == 0 ) { + job_dispatch(spi->j, false); + free(spi); } + } else { + kr = 1; } break; case 0: @@ -8437,7 +8456,7 @@ } char name[NAME_MAX]; - snprintf(name, sizeof(name), "bootstrap_subset(%u)->%s[%i]", MACH_PORT_INDEX(requestorport), j->anonymous ? j->prog : j->label, j->p); + snprintf(name, sizeof(name), "%s[%i].subset.%i", j->anonymous ? j->prog : j->label, j->p, MACH_PORT_INDEX(requestorport)); if (!job_assumes(j, (jmr = jobmgr_new(j->mgr, requestorport, MACH_PORT_NULL, false, name, j->audit_session)) != NULL)) { if (unlikely(requestorport == MACH_PORT_NULL)) { Modified: trunk/launchd/src/libvproc.c =================================================================== --- trunk/launchd/src/libvproc.c 2009-04-09 18:05:32 UTC (rev 23888) +++ trunk/launchd/src/libvproc.c 2009-04-10 01:56:53 UTC (rev 23889) @@ -842,8 +842,9 @@ break; } + kern_return_t kr = KERN_FAILURE; mach_port_t mp = vp ? vp->j_port : bootstrap_port; - if (vproc_mig_swap_integer(mp, inval ? key : 0, outval ? key : 0, inval ? *inval : 0, outval ? outval : &dummyval) == 0) { + if ((kr = vproc_mig_swap_integer(mp, inval ? key : 0, outval ? key : 0, inval ? *inval : 0, outval ? outval : &dummyval)) == 0) { switch (key) { case VPROC_GSK_MGR_PID: cached_pid = outval ? *outval : dummyval; @@ -862,10 +863,8 @@ vproc_t pu_vp = vprocmgr_lookup_vproc(peruser_label); if( pu_vp ) { int status = 0; - kern_return_t kr = vproc_mig_wait2(bootstrap_port, pu_vp->j_port, &status); + kr = vproc_mig_wait2(bootstrap_port, pu_vp->j_port, &status); vproc_release(pu_vp); - - syslog(LOG_DEBUG, "%u's suspended launchd exited with status %i (kr = 0x%x).", (uid_t)*inval, status, kr); } break; }
participants (1)
-
source_changes@macosforge.org