Revision: 23701 http://trac.macosforge.org/projects/launchd/changeset/23701 Author: dsorresso@apple.com Date: 2008-08-27 11:32:52 -0700 (Wed, 27 Aug 2008) Log Message: ----------- Merging changes for rdar://problem/5898404. Modified Paths: -------------- trunk/launchd/src/launchd_core_logic.c trunk/launchd/src/launchd_runtime.c trunk/launchd/src/libvproc.c trunk/launchd/src/libvproc_private.h Property Changed: ---------------- trunk/ Property changes on: trunk ___________________________________________________________________ Added: svn:mergeinfo + /branches/PR-5898404:23681-23700 Modified: trunk/launchd/src/launchd_core_logic.c =================================================================== --- trunk/launchd/src/launchd_core_logic.c 2008-08-25 21:11:32 UTC (rev 23700) +++ trunk/launchd/src/launchd_core_logic.c 2008-08-27 18:32:52 UTC (rev 23701) @@ -336,7 +336,7 @@ #define AUTO_PICK_LEGACY_LABEL (const char *)(~0) struct job_s { - kq_callback kqjob_callback; + kq_callback kqjob_callback; /* MUST be first element of this structure for benefit of launchd's run loop. */ LIST_ENTRY(job_s) sle; LIST_ENTRY(job_s) pid_hash_sle; LIST_ENTRY(job_s) label_hash_sle; @@ -1055,6 +1055,11 @@ job_assumes(j, kevent_mod((uintptr_t)&j->semaphores, EVFILT_TIMER, EV_DELETE, 0, 0, j) != -1); } + if( j->exit_timeout ) { + /* Not a big deal if this fails. It means that the timer's already been freed. */ + kevent_mod((uintptr_t)&j->exit_timeout, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + } + kevent_mod((uintptr_t)j, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); LIST_REMOVE(j, sle); @@ -6046,6 +6051,10 @@ *outval = oldmask; umask(oldmask); break; + case VPROC_GSK_TRANSACTIONS_ENABLED: + job_log(j, LOG_DEBUG, "Reading transaction model status."); + *outval = j->kill_via_shmem; + break; case 0: *outval = 0; break; @@ -6110,6 +6119,15 @@ umask((mode_t) inval); } break; + case VPROC_GSK_TRANSACTIONS_ENABLED: + if( !job_assumes(j, inval != 0) ) { + job_log(j, LOG_WARNING, "Attempt to unregister from transaction model. This is not supported."); + kr = 1; + } else { + job_log(j, LOG_DEBUG, "Now participating in transaction model."); + j->kill_via_shmem = (bool)inval; + job_log(j, LOG_DEBUG, "j->kill_via_shmem = %s", j->kill_via_shmem ? "YES" : "NO"); + } case 0: break; default: Modified: trunk/launchd/src/launchd_runtime.c =================================================================== --- trunk/launchd/src/launchd_runtime.c 2008-08-25 21:11:32 UTC (rev 23700) +++ trunk/launchd/src/launchd_runtime.c 2008-08-27 18:32:52 UTC (rev 23701) @@ -616,9 +616,15 @@ kevi = &kev[i]; if (kevi->filter) { +/* Leave on for SnowLeopard development. We should really try and identify what bugs would + * cause kevi->udata to be invalid. + */ #if 1 Dl_info dli; + /* Check if kevi->udata was either malloc(3)ed or is a valid function pointer. + * If neither, it's probably an invalid pointer and we should log it. + */ if (launchd_assumes(malloc_size(kevi->udata) || dladdr(kevi->udata, &dli))) { #endif runtime_ktrace(RTKT_LAUNCHD_BSD_KEVENT|DBG_FUNC_START, kevi->ident, kevi->filter, kevi->fflags); Modified: trunk/launchd/src/libvproc.c =================================================================== --- trunk/launchd/src/libvproc.c 2008-08-25 21:11:32 UTC (rev 23700) +++ trunk/launchd/src/libvproc.c 2008-08-27 18:32:52 UTC (rev 23701) @@ -56,6 +56,7 @@ static int64_t cached_pid = -1; static struct vproc_shmem_s *vproc_shmem; static pthread_once_t shmem_inited = PTHREAD_ONCE_INIT; +static uint64_t s_cached_transactions_enabled = 0; static void vproc_shmem_init(void) @@ -95,8 +96,6 @@ void _vproc_transaction_begin(void) { - typeof(vproc_shmem->vp_shmem_transaction_cnt) newval; - if (unlikely(vproc_shmem == NULL)) { int po_r = pthread_once(&shmem_inited, vproc_shmem_init); if (po_r != 0 || vproc_shmem == NULL) { @@ -104,17 +103,20 @@ } } - newval = __sync_add_and_fetch(&vproc_shmem->vp_shmem_transaction_cnt, 1); - - if (unlikely(newval < 1)) { - if (vproc_shmem->vp_shmem_flags & VPROC_SHMEM_EXITING) { - raise(SIGKILL); - __crashreporter_info__ = "raise(SIGKILL) failed"; - } else { - __crashreporter_info__ = "Unbalanced: vproc_transaction_begin()"; + typeof(vproc_shmem->vp_shmem_transaction_cnt) old = 0; + do { + old = vproc_shmem->vp_shmem_transaction_cnt; + + if (unlikely(old < 0)) { + if (vproc_shmem->vp_shmem_flags & VPROC_SHMEM_EXITING) { + raise(SIGKILL); + __crashreporter_info__ = "raise(SIGKILL) failed"; + } else { + __crashreporter_info__ = "Unbalanced: vproc_transaction_begin()"; + } + abort(); } - abort(); - } + } while( !__sync_bool_compare_and_swap(&vproc_shmem->vp_shmem_transaction_cnt, old, old + 1) ); } size_t @@ -643,6 +645,23 @@ return NULL; } break; + case VPROC_GSK_TRANSACTIONS_ENABLED: + /* Shared memory region is required for transactions. */ + if( unlikely(vproc_shmem == NULL) ) { + int po_r = pthread_once(&shmem_inited, vproc_shmem_init); + if( po_r != 0 || vproc_shmem == NULL ) { + if( outval ) { + *outval = -1; + } + return (vproc_err_t)vproc_swap_integer; + } + } + + if( s_cached_transactions_enabled && outval ) { + *outval = s_cached_transactions_enabled; + return NULL; + } + break; default: break; } @@ -655,6 +674,10 @@ case VPROC_GSK_IS_MANAGED: cached_is_managed = outval ? *outval : dummyval; break; + case VPROC_GSK_TRANSACTIONS_ENABLED: + /* Once you're in the transaction model, you're in for good. Like the Mafia. */ + s_cached_transactions_enabled = 1; + break; default: break; } Modified: trunk/launchd/src/libvproc_private.h =================================================================== --- trunk/launchd/src/libvproc_private.h 2008-08-25 21:11:32 UTC (rev 23700) +++ trunk/launchd/src/libvproc_private.h 2008-08-27 18:32:52 UTC (rev 23701) @@ -51,6 +51,7 @@ VPROC_GSK_GLOBAL_LOG_MASK, VPROC_GSK_GLOBAL_UMASK, VPROC_GSK_ABANDON_PROCESS_GROUP, + VPROC_GSK_TRANSACTIONS_ENABLED } vproc_gsk_t; vproc_err_t vproc_swap_integer(vproc_t vp, vproc_gsk_t key, int64_t *inval, int64_t *outval);