From 052e63f27f7b1edf5635d6a266653fe77c42941c Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Thu, 6 Sep 2012 16:06:15 +0200 Subject: [PATCH] v8: fix semaphore on MacOS Landed upstream: https://chromiumcodereview.appspot.com/10867009/ --- deps/v8/src/platform-macos.cc | 22 ++++++++--- deps/v8/test/cctest/test-api.cc | 70 +++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/deps/v8/src/platform-macos.cc b/deps/v8/src/platform-macos.cc index a937ed3a5c1..a216f6e4cac 100644 --- a/deps/v8/src/platform-macos.cc +++ b/deps/v8/src/platform-macos.cc @@ -682,17 +682,27 @@ Mutex* OS::CreateMutex() { class MacOSSemaphore : public Semaphore { public: explicit MacOSSemaphore(int count) { - semaphore_create(mach_task_self(), &semaphore_, SYNC_POLICY_FIFO, count); + int r; + r = semaphore_create(mach_task_self(), + &semaphore_, + SYNC_POLICY_FIFO, + count); + ASSERT(r == KERN_SUCCESS); } ~MacOSSemaphore() { - semaphore_destroy(mach_task_self(), semaphore_); + int r; + r = semaphore_destroy(mach_task_self(), semaphore_); + ASSERT(r == KERN_SUCCESS); } - // The MacOS mach semaphore documentation claims it does not have spurious - // wakeups, the way pthreads semaphores do. So the code from the linux - // platform is not needed here. - void Wait() { semaphore_wait(semaphore_); } + void Wait() { + int r; + do { + r = semaphore_wait(semaphore_); + ASSERT(r == KERN_SUCCESS || r == KERN_ABORTED); + } while (r == KERN_ABORTED); + } bool Wait(int timeout); diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index df810597a1e..e24782085f6 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -27,6 +27,11 @@ #include +#ifndef WIN32 +#include // kill +#include // getpid +#endif // WIN32 + #include "v8.h" #include "api.h" @@ -17017,3 +17022,68 @@ THREADED_TEST(Regress142088) { CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined()); CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined()); } + + +#ifndef WIN32 +class ThreadInterruptTest { + public: + ThreadInterruptTest() : sem_(NULL), sem_value_(0) { } + ~ThreadInterruptTest() { delete sem_; } + + void RunTest() { + sem_ = i::OS::CreateSemaphore(0); + + InterruptThread i_thread(this); + i_thread.Start(); + + sem_->Wait(); + CHECK_EQ(kExpectedValue, sem_value_); + } + + private: + static const int kExpectedValue = 1; + + class InterruptThread : public i::Thread { + public: + explicit InterruptThread(ThreadInterruptTest* test) + : Thread("InterruptThread"), test_(test) {} + + virtual void Run() { + struct sigaction action; + + // Ensure that we'll enter waiting condition + i::OS::Sleep(100); + + // Setup signal handler + memset(&action, 0, sizeof(action)); + action.sa_handler = SignalHandler; + sigaction(SIGCHLD, &action, NULL); + + // Send signal + kill(getpid(), SIGCHLD); + + // Ensure that if wait has returned because of error + i::OS::Sleep(100); + + // Set value and signal semaphore + test_->sem_value_ = 1; + test_->sem_->Signal(); + } + + static void SignalHandler(int signal) { + } + + private: + ThreadInterruptTest* test_; + struct sigaction sa_; + }; + + i::Semaphore* sem_; + volatile int sem_value_; +}; + + +THREADED_TEST(SemaphoreInterruption) { + ThreadInterruptTest().RunTest(); +} +#endif // WIN32