Revision: 23580 http://trac.macosforge.org/projects/launchd/changeset/23580 Author: zarzycki@apple.com Date: 2008-03-28 12:47:54 -0700 (Fri, 28 Mar 2008) Log Message: ----------- Have launchd use the kill-via-shmem trick. Modified Paths: -------------- trunk/launchd/src/launchd.c trunk/launchd/src/launchd_core_logic.c trunk/launchd/src/launchd_runtime.c trunk/launchd/src/launchd_runtime.h trunk/launchd/src/libvproc.c trunk/launchd/src/libvproc_internal.h trunk/launchd/src/libvproc_private.h Modified: trunk/launchd/src/launchd.c =================================================================== --- trunk/launchd/src/launchd.c 2008-03-27 22:56:23 UTC (rev 23579) +++ trunk/launchd/src/launchd.c 2008-03-28 19:47:54 UTC (rev 23580) @@ -70,6 +70,7 @@ #include "libbootstrap_public.h" #include "libvproc_public.h" +#include "libvproc_private.h" #include "libvproc_internal.h" #include "liblaunch_public.h" @@ -158,6 +159,10 @@ if (pid1_magic) { handle_pid1_crashes_separately(); + } else { + /* prime shared memory before the 'bootstrap_port' global is set to zero */ + _vproc_transaction_begin(); + _vproc_transaction_end(); } jobmgr_init(sflag); Modified: trunk/launchd/src/launchd_core_logic.c =================================================================== --- trunk/launchd/src/launchd_core_logic.c 2008-03-27 22:56:23 UTC (rev 23579) +++ trunk/launchd/src/launchd_core_logic.c 2008-03-28 19:47:54 UTC (rev 23580) @@ -563,6 +563,7 @@ INTERNAL_ABI void job_stop(job_t j) { + char extralog[100]; int32_t newval = 1; if (unlikely(!j->p || j->anonymous)) { @@ -595,7 +596,13 @@ EV_ADD|EV_ONESHOT, NOTE_SECONDS, j->exit_timeout, j) != -1); } - job_log(j, LOG_DEBUG, "Sent SIGTERM signal"); + if (j->kill_via_shmem) { + snprintf(extralog, sizeof(extralog), ": %d remaining transactions", j->shmem->vp_shmem_transaction_cnt + 1); + } else { + extralog[0] = '\0'; + } + + job_log(j, LOG_DEBUG, "Sent SIGTERM signal%s", extralog); } } @@ -803,7 +810,7 @@ } if (jm->parentmgr) { - runtime_del_ref(); + runtime_del_weak_ref(); SLIST_REMOVE(&jm->parentmgr->submgrs, jm, jobmgr_s, sle); } else if (pid1_magic) { jobmgr_log(jm, LOG_DEBUG, "About to call: sync()"); @@ -959,7 +966,7 @@ free(j->j_binpref); } if (j->start_interval) { - runtime_del_ref(); + runtime_del_weak_ref(); job_assumes(j, kevent_mod((uintptr_t)&j->start_interval, EVFILT_TIMER, EV_DELETE, 0, 0, NULL) != -1); } if (j->poll_for_vfs_changes) { @@ -1664,7 +1671,7 @@ } else if (unlikely(value > UINT32_MAX)) { job_log(j, LOG_WARNING, "%s is too large. Ignoring.", LAUNCH_JOBKEY_STARTINTERVAL); } else { - runtime_add_ref(); + runtime_add_weak_ref(); j->start_interval = value; job_assumes(j, kevent_mod((uintptr_t)&j->start_interval, EVFILT_TIMER, EV_ADD, NOTE_SECONDS, value, j) != -1); @@ -2230,7 +2237,7 @@ job_log(j, LOG_DEBUG, "Reaping"); if (j->shmem) { - job_assumes(j, munmap(j->shmem, getpagesize()) == 0); + job_assumes(j, vm_deallocate(mach_task_self(), (vm_address_t)j->shmem, getpagesize()) == 0); j->shmem = NULL; } @@ -3791,7 +3798,7 @@ calendarinterval_setalarm(j, ci); - runtime_add_ref(); + runtime_add_weak_ref(); return true; } @@ -3804,7 +3811,7 @@ free(ci); - runtime_del_ref(); + runtime_del_weak_ref(); } void @@ -3862,7 +3869,7 @@ SLIST_INSERT_HEAD(&j->sockets, sg, sle); - runtime_add_ref(); + runtime_add_weak_ref(); return true; } @@ -3893,7 +3900,7 @@ free(sg->fds); free(sg); - runtime_del_ref(); + runtime_del_weak_ref(); } void @@ -4729,7 +4736,7 @@ } if (jmr->parentmgr) { - runtime_add_ref(); + runtime_add_weak_ref(); } return jmr; @@ -5169,9 +5176,9 @@ } if (add) { - runtime_add_ref(); + runtime_add_weak_ref(); } else { - runtime_del_ref(); + runtime_del_weak_ref(); } } @@ -5437,6 +5444,7 @@ job_mig_setup_shmem(job_t j, mach_port_t *shmem_port) { memory_object_size_t size_of_page, size_of_page_orig; + vm_address_t vm_addr; kern_return_t kr; if (!launchd_assumes(j != NULL)) { @@ -5444,6 +5452,7 @@ } if (unlikely(j->anonymous)) { + job_log(j, LOG_ERR, "Anonymous job tried to setup shared memory"); return BOOTSTRAP_NOT_PRIVILEGED; } @@ -5454,17 +5463,25 @@ size_of_page_orig = size_of_page = getpagesize(); - if (!job_assumes(j, j->shmem = mmap(NULL, size_of_page, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0))) { - return BOOTSTRAP_NO_MEMORY; + kr = vm_allocate(mach_task_self(), &vm_addr, size_of_page, true); + + if (!job_assumes(j, kr == 0)) { + return kr; } + j->shmem = (typeof(j->shmem))vm_addr; + j->shmem->vp_shmem_standby_timeout = j->timeout; + kr = mach_make_memory_entry_64(mach_task_self(), &size_of_page, - (memory_object_offset_t)((long)j->shmem), VM_PROT_DEFAULT, shmem_port, 0); + (memory_object_offset_t)vm_addr, VM_PROT_READ|VM_PROT_WRITE, shmem_port, 0); if (job_assumes(j, kr == 0)) { job_assumes(j, size_of_page == size_of_page_orig); } + /* no need to inherit this in child processes */ + job_assumes(j, vm_inherit(mach_task_self(), (vm_address_t)j->shmem, size_of_page_orig, VM_INHERIT_NONE) == 0); + return kr; } @@ -5776,7 +5793,7 @@ kr = 1; } else if (inval) { if (j->start_interval == 0) { - runtime_add_ref(); + runtime_add_weak_ref(); } else { /* Workaround 5225889 */ job_assumes(j, kevent_mod((uintptr_t)&j->start_interval, EVFILT_TIMER, EV_DELETE, 0, 0, j) != -1); @@ -5786,7 +5803,7 @@ } else if (j->start_interval) { job_assumes(j, kevent_mod((uintptr_t)&j->start_interval, EVFILT_TIMER, EV_DELETE, 0, 0, NULL) != -1); if (j->start_interval != 0) { - runtime_del_ref(); + runtime_del_weak_ref(); } j->start_interval = 0; } @@ -6014,6 +6031,7 @@ ji->mach_uid = which_user; ji->per_user = true; + ji->kill_via_shmem = true; if ((ms = machservice_new(ji, lbuf, up_cont, false)) == NULL) { job_remove(ji); Modified: trunk/launchd/src/launchd_runtime.c =================================================================== --- trunk/launchd/src/launchd_runtime.c 2008-03-27 22:56:23 UTC (rev 23579) +++ trunk/launchd/src/launchd_runtime.c 2008-03-28 19:47:54 UTC (rev 23580) @@ -69,6 +69,8 @@ #include "launch.h" #include "launchd.h" #include "launchd_core_logic.h" +#include "libvproc_public.h" +#include "libvproc_private.h" #include "libvproc_internal.h" #include "job_reply.h" @@ -99,6 +101,7 @@ static mach_msg_timeout_t runtime_idle_timeout; static struct ldcred ldc; static size_t runtime_busy_cnt; +static size_t runtime_standby_cnt; static STAILQ_HEAD(, logmsg_s) logmsg_queue = STAILQ_HEAD_INITIALIZER(logmsg_queue); @@ -989,6 +992,7 @@ mig_callback the_demux; mach_msg_timeout_t to; mach_msg_return_t mr; + size_t busy_cnt; options = MACH_RCV_MSG|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0); @@ -996,6 +1000,7 @@ tmp_options = options; for (;;) { + busy_cnt = runtime_busy_cnt + runtime_standby_cnt; to = MACH_MSG_TIMEOUT_NONE; if (unlikely(msg_size != max_msg_size)) { @@ -1007,11 +1012,11 @@ } } - if ((tmp_options & MACH_RCV_MSG) && (runtime_idle_callback || (runtime_busy_cnt == 0))) { + if ((tmp_options & MACH_RCV_MSG) && (runtime_idle_callback || (busy_cnt == 0))) { tmp_options |= MACH_RCV_TIMEOUT; if (!(tmp_options & MACH_SEND_TIMEOUT)) { - to = runtime_busy_cnt ? runtime_idle_timeout : (RUNTIME_ADVISABLE_IDLE_TIMEOUT * 1000); + to = busy_cnt ? runtime_idle_timeout : (_vproc_standby_timeout() * 1000); } } @@ -1033,7 +1038,7 @@ continue; case MACH_RCV_TIMED_OUT: if (to != MACH_MSG_TIMEOUT_NONE) { - if (runtime_busy_cnt == 0) { + if (busy_cnt == 0) { launchd_shutdown(); } else if (runtime_idle_callback) { runtime_idle_callback(); @@ -1477,15 +1482,39 @@ INTERNAL_ABI void runtime_add_ref(void) { + if (!pid1_magic) { + _vproc_transaction_begin(); + } runtime_busy_cnt++; } INTERNAL_ABI void runtime_del_ref(void) { + if (!pid1_magic) { + _vproc_transaction_end(); + } runtime_busy_cnt--; } +INTERNAL_ABI void +runtime_add_weak_ref(void) +{ + if (!pid1_magic) { + _vproc_standby_begin(); + } + runtime_standby_cnt++; +} + +INTERNAL_ABI void +runtime_del_weak_ref(void) +{ + if (!pid1_magic) { + _vproc_standby_end(); + } + runtime_standby_cnt--; +} + kern_return_t catch_mach_exception_raise(mach_port_t exception_port __attribute__((unused)), mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) Modified: trunk/launchd/src/launchd_runtime.h =================================================================== --- trunk/launchd/src/launchd_runtime.h 2008-03-27 22:56:23 UTC (rev 23579) +++ trunk/launchd/src/launchd_runtime.h 2008-03-28 19:47:54 UTC (rev 23580) @@ -111,6 +111,8 @@ INTERNAL_ABI void runtime_add_ref(void); INTERNAL_ABI void runtime_del_ref(void); +INTERNAL_ABI void runtime_add_weak_ref(void); +INTERNAL_ABI void runtime_del_weak_ref(void); INTERNAL_ABI void launchd_runtime_init(void); INTERNAL_ABI void launchd_runtime_init2(void); Modified: trunk/launchd/src/libvproc.c =================================================================== --- trunk/launchd/src/libvproc.c 2008-03-27 22:56:23 UTC (rev 23579) +++ trunk/launchd/src/libvproc.c 2008-03-28 19:47:54 UTC (rev 23580) @@ -33,6 +33,7 @@ #include <syslog.h> #include <pthread.h> #include <signal.h> +#include <assert.h> #if HAVE_QUARANTINE #include <quarantine.h> #endif @@ -65,16 +66,12 @@ kr = vproc_mig_setup_shmem(bootstrap_port, &shmem_port); - if (unlikely(kr)) { - abort(); - } + assert(kr == 0); - kr = vm_map_64(mach_task_self(), &vm_addr, getpagesize(), 0, true, shmem_port, 0, false, + kr = vm_map(mach_task_self(), &vm_addr, getpagesize(), 0, true, shmem_port, 0, false, VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE, VM_INHERIT_NONE); - if (unlikely(kr)) { - abort(); - } + assert(kr == 0); vproc_shmem = (struct vproc_shmem_s *)vm_addr; } @@ -84,13 +81,13 @@ { vproc_transaction_t vpt = (vproc_transaction_t)vproc_shmem_init; /* we need a "random" variable that is testable */ - _basic_vproc_transaction_begin(); + _vproc_transaction_begin(); return vpt; } void -_basic_vproc_transaction_begin(void) +_vproc_transaction_begin(void) { typeof(vproc_shmem->vp_shmem_transaction_cnt) newval; @@ -115,13 +112,25 @@ } size_t -_basic_vproc_transaction_count(void) +_vproc_transaction_count(void) { return likely(vproc_shmem) ? vproc_shmem->vp_shmem_transaction_cnt : INT32_MAX; } +size_t +_vproc_standby_count(void) +{ + return likely(vproc_shmem) ? vproc_shmem->vp_shmem_standby_cnt : INT32_MAX; +} + +size_t +_vproc_standby_timeout(void) +{ + return likely(vproc_shmem) ? vproc_shmem->vp_shmem_standby_timeout : 0; +} + void -_basic_vproc_transaction_try_exit(int status) +_vproc_transaction_try_exit(int status) { typeof(vproc_shmem->vp_shmem_transaction_cnt) newval; @@ -146,11 +155,11 @@ abort(); } - _basic_vproc_transaction_end(); + _vproc_transaction_end(); } void -_basic_vproc_transaction_end(void) +_vproc_transaction_end(void) { typeof(vproc_shmem->vp_shmem_transaction_cnt) newval; @@ -171,12 +180,21 @@ vproc_standby_begin(vproc_t vp __attribute__((unused))) { vproc_standby_t vpsb = (vproc_standby_t)vproc_shmem_init; /* we need a "random" variable that is testable */ + + _vproc_standby_begin(); + + return vpsb; +} + +void +_vproc_standby_begin(void) +{ typeof(vproc_shmem->vp_shmem_standby_cnt) newval; if (unlikely(vproc_shmem == NULL)) { int po_r = pthread_once(&shmem_inited, vproc_shmem_init); if (po_r != 0 || vproc_shmem == NULL) { - return NULL; + return; } } @@ -186,20 +204,24 @@ __crashreporter_info__ = "Unbalanced: vproc_standby_begin()"; abort(); } - - return vpsb; } void vproc_standby_end(vproc_t vp __attribute__((unused)), vproc_standby_t vpt) { - typeof(vproc_shmem->vp_shmem_standby_cnt) newval; - if (unlikely(vpt != (vproc_standby_t)vproc_shmem_init)) { __crashreporter_info__ = "Bogus standby handle passed to vproc_standby_end() "; abort(); } + _vproc_standby_end(); +} + +void +_vproc_standby_end(void) +{ + typeof(vproc_shmem->vp_shmem_standby_cnt) newval; + newval = __sync_sub_and_fetch(&vproc_shmem->vp_shmem_standby_cnt, 1); if (unlikely(newval < 0)) { Modified: trunk/launchd/src/libvproc_internal.h =================================================================== --- trunk/launchd/src/libvproc_internal.h 2008-03-27 22:56:23 UTC (rev 23579) +++ trunk/launchd/src/libvproc_internal.h 2008-03-28 19:47:54 UTC (rev 23580) @@ -38,6 +38,7 @@ struct vproc_shmem_s { int32_t vp_shmem_transaction_cnt; int32_t vp_shmem_standby_cnt; + uint32_t vp_shmem_standby_timeout; int32_t vp_shmem_flags; }; Modified: trunk/launchd/src/libvproc_private.h =================================================================== --- trunk/launchd/src/libvproc_private.h 2008-03-27 22:56:23 UTC (rev 23579) +++ trunk/launchd/src/libvproc_private.h 2008-03-28 19:47:54 UTC (rev 23580) @@ -76,12 +76,17 @@ vproc_err_t _vprocmgr_move_subset_to_user(uid_t target_user, const char *session_type); -void _basic_vproc_transaction_begin(void); -void _basic_vproc_transaction_end(void); -size_t _basic_vproc_transaction_count(void); -void _basic_vproc_transaction_try_exit(int status); +void _vproc_standby_begin(void); +void _vproc_standby_end(void); +size_t _vproc_standby_count(void); +size_t _vproc_standby_timeout(void); +void _vproc_transaction_try_exit(int status); +void _vproc_transaction_begin(void); +void _vproc_transaction_end(void); +size_t _vproc_transaction_count(void); + #pragma GCC visibility pop __END_DECLS
participants (1)
-
source_changes@macosforge.org