mirror of https://github.com/nodejs/node.git
v8: fix semaphore on MacOS
Landed upstream: https://chromiumcodereview.appspot.com/10867009/v0.8.16-release
parent
c5e554dc7e
commit
052e63f27f
|
@ -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);
|
||||
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <signal.h> // kill
|
||||
#include <unistd.h> // 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
|
||||
|
|
Loading…
Reference in New Issue