From c6094f5237dd0bf51d31f8eb7d4f588683d73f17 Mon Sep 17 00:00:00 2001 From: erikcorry Date: Thu, 23 Aug 2012 11:15:06 +0000 Subject: [PATCH] Fix semaphore on MacOS. This is a commit of https://chromiumcodereview.appspot.com/10867009/ for Fedor Indutny git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12371 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/platform-macos.cc | 22 +++++++++---- test/cctest/test-api.cc | 70 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/platform-macos.cc b/src/platform-macos.cc index a937ed3a5..a216f6e4c 100644 --- a/src/platform-macos.cc +++ b/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/test/cctest/test-api.cc b/test/cctest/test-api.cc index 87e3c0c10..79158ae4b 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -28,6 +28,11 @@ #include +#ifndef WIN32 +#include // kill +#include // getpid +#endif // WIN32 + #include "v8.h" #include "api.h" @@ -17194,3 +17199,68 @@ THREADED_TEST(Regress137496) { CompileRun("try { throw new Error(); } finally { gc(); }"); CHECK(try_catch.HasCaught()); } + + +#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 -- 2.34.1