diff --git a/ipc/glue/CrossProcessSemaphore_mach.cpp b/ipc/glue/CrossProcessSemaphore_mach.cpp index 41cdd73010eb..d7cccee2a007 100644 --- a/ipc/glue/CrossProcessSemaphore_mach.cpp +++ b/ipc/glue/CrossProcessSemaphore_mach.cpp @@ -7,6 +7,7 @@ #include "CrossProcessSemaphore.h" #include "nsDebug.h" #include "nsISupportsImpl.h" +#include static const uint64_t kNsPerUs = 1000; static const uint64_t kNsPerSec = 1000000000; @@ -47,14 +48,33 @@ CrossProcessSemaphore::~CrossProcessSemaphore() { bool CrossProcessSemaphore::Wait(const Maybe& aWaitTime) { MOZ_ASSERT(mSemaphore, "Improper construction of semaphore."); + int kr = KERN_OPERATION_TIMED_OUT; + // semaphore_(timed)wait may be interrupted by KERN_ABORTED. Carefully restart + // the wait until it either succeeds or times out. if (aWaitTime.isNothing()) { - return semaphore_wait(mSemaphore.get()) == KERN_SUCCESS; + do { + kr = semaphore_wait(mSemaphore.get()); + } while (kr == KERN_ABORTED); + } else { + mach_timebase_info_data_t tb; + if (mach_timebase_info(&tb) != KERN_SUCCESS) { + return false; + } + uint64_t now = (mach_absolute_time() * tb.numer) / tb.denom; + uint64_t deadline = now + uint64_t(kNsPerUs * aWaitTime->ToMicroseconds()); + while (now <= deadline) { + uint64_t ns = deadline - now; + mach_timespec_t ts; + ts.tv_sec = ns / kNsPerSec; + ts.tv_nsec = ns % kNsPerSec; + kr = semaphore_timedwait(mSemaphore.get(), ts); + if (kr != KERN_ABORTED) { + break; + } + now = (mach_absolute_time() * tb.numer) / tb.denom; + } } - uint64_t ns = uint64_t(kNsPerUs * aWaitTime->ToMicroseconds()); - mach_timespec_t ts; - ts.tv_sec = ns / kNsPerSec; - ts.tv_nsec = ns % kNsPerSec; - return semaphore_timedwait(mSemaphore.get(), ts) == KERN_SUCCESS; + return kr == KERN_SUCCESS; } void CrossProcessSemaphore::Signal() {