Commit 715434d7 authored by Kenton Varda's avatar Kenton Varda

Try to work around OSX's crappy signal handling behavior.

parent 87fd6e8c
...@@ -34,6 +34,13 @@ namespace kj { ...@@ -34,6 +34,13 @@ namespace kj {
inline void delay() { usleep(10000); } inline void delay() { usleep(10000); }
// On OSX, si_code seems to be zero when SI_USER is expected.
#if __linux__ || __CYGWIN__
#define EXPECT_SI_CODE EXPECT_EQ
#else
#define EXPECT_SI_CODE(a,b)
#endif
class DummyErrorHandler: public TaskSet::ErrorHandler { class DummyErrorHandler: public TaskSet::ErrorHandler {
public: public:
void taskFailed(kj::Exception&& exception) override { void taskFailed(kj::Exception&& exception) override {
...@@ -56,7 +63,7 @@ TEST_F(AsyncUnixTest, Signals) { ...@@ -56,7 +63,7 @@ TEST_F(AsyncUnixTest, Signals) {
siginfo_t info = loop.wait(loop.onSignal(SIGUSR2)); siginfo_t info = loop.wait(loop.onSignal(SIGUSR2));
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGUSR2, info.si_signo);
EXPECT_EQ(SI_USER, info.si_code); EXPECT_SI_CODE(SI_USER, info.si_code);
} }
#ifdef SIGRTMIN #ifdef SIGRTMIN
...@@ -74,7 +81,7 @@ TEST_F(AsyncUnixTest, SignalWithValue) { ...@@ -74,7 +81,7 @@ TEST_F(AsyncUnixTest, SignalWithValue) {
siginfo_t info = loop.wait(loop.onSignal(SIGUSR2)); siginfo_t info = loop.wait(loop.onSignal(SIGUSR2));
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGUSR2, info.si_signo);
EXPECT_EQ(SI_QUEUE, info.si_code); EXPECT_SI_CODE(SI_QUEUE, info.si_code);
EXPECT_EQ(123, info.si_value.sival_int); EXPECT_EQ(123, info.si_value.sival_int);
} }
#endif #endif
...@@ -92,7 +99,7 @@ TEST_F(AsyncUnixTest, SignalsMulti) { ...@@ -92,7 +99,7 @@ TEST_F(AsyncUnixTest, SignalsMulti) {
siginfo_t info = loop.wait(loop.onSignal(SIGUSR2)); siginfo_t info = loop.wait(loop.onSignal(SIGUSR2));
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGUSR2, info.si_signo);
EXPECT_EQ(SI_USER, info.si_code); EXPECT_SI_CODE(SI_USER, info.si_code);
} }
TEST_F(AsyncUnixTest, SignalsAsync) { TEST_F(AsyncUnixTest, SignalsAsync) {
...@@ -110,14 +117,14 @@ TEST_F(AsyncUnixTest, SignalsAsync) { ...@@ -110,14 +117,14 @@ TEST_F(AsyncUnixTest, SignalsAsync) {
[&](siginfo_t&& info) { [&](siginfo_t&& info) {
received = true; received = true;
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGUSR2, info.si_signo);
EXPECT_EQ(SI_USER, info.si_code); EXPECT_SI_CODE(SI_TKILL, info.si_code);
}); });
delay(); delay();
EXPECT_FALSE(received); EXPECT_FALSE(received);
kill(getpid(), SIGUSR2); thread.sendSignal(SIGUSR2);
SimpleEventLoop mainLoop; SimpleEventLoop mainLoop;
mainLoop.wait(kj::mv(promise)); mainLoop.wait(kj::mv(promise));
......
...@@ -469,15 +469,22 @@ void UnixEventLoop::sleep() { ...@@ -469,15 +469,22 @@ void UnixEventLoop::sleep() {
sigset_t origMask; sigset_t origMask;
sigprocmask(SIG_UNBLOCK, &newMask, &origMask); sigprocmask(SIG_UNBLOCK, &newMask, &origMask);
int pollResult = poll(pollfds.begin(), pollfds.size(), -1); int pollResult;
int error = pollResult < 0 ? errno : 0; int pollError;
do {
pollResult = poll(pollfds.begin(), pollfds.size(), -1);
pollError = pollResult < 0 ? errno : 0;
// EINTR should only happen if we received a signal *other than* the ones registered via
// the UnixEventLoop, so we don't care about that case.
} while (pollError == EINTR);
sigprocmask(SIG_SETMASK, &origMask, nullptr); sigprocmask(SIG_SETMASK, &origMask, nullptr);
threadCapture = nullptr; threadCapture = nullptr;
__atomic_store_n(&isSleeping, false, __ATOMIC_RELAXED); __atomic_store_n(&isSleeping, false, __ATOMIC_RELAXED);
if (pollResult < 0) { if (pollResult < 0) {
KJ_FAIL_SYSCALL("poll()", error); KJ_FAIL_SYSCALL("poll()", pollError);
} }
for (auto i: indices(pollfds)) { for (auto i: indices(pollfds)) {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "thread.h" #include "thread.h"
#include "debug.h" #include "debug.h"
#include <pthread.h> #include <pthread.h>
#include <signal.h>
namespace kj { namespace kj {
...@@ -39,7 +40,17 @@ Thread::Thread(void* (*run)(void*), void (*deleteArg)(void*), void* arg) { ...@@ -39,7 +40,17 @@ Thread::Thread(void* (*run)(void*), void (*deleteArg)(void*), void* arg) {
} }
Thread::~Thread() { Thread::~Thread() {
KJ_ASSERT(pthread_join(*reinterpret_cast<pthread_t*>(&threadId), nullptr) == 0); int pthreadResult = pthread_join(*reinterpret_cast<pthread_t*>(&threadId), nullptr);
if (pthreadResult != 0) {
KJ_FAIL_SYSCALL("pthread_join", pthreadResult) { break; }
}
}
void Thread::sendSignal(int signo) {
int pthreadResult = pthread_kill(*reinterpret_cast<pthread_t*>(&threadId), signo);
if (pthreadResult != 0) {
KJ_FAIL_SYSCALL("pthread_kill", pthreadResult) { break; }
}
} }
} // namespace kj } // namespace kj
...@@ -40,6 +40,9 @@ public: ...@@ -40,6 +40,9 @@ public:
~Thread(); ~Thread();
void sendSignal(int signo);
// Send a Unix signal to the given thread, using pthread_kill or an equivalent.
private: private:
unsigned long long threadId; // actually pthread_t unsigned long long threadId; // actually pthread_t
......
linux-gcc-4.7 1630 ./super-test.sh tmpdir capnp-gcc-4.7 quick linux-gcc-4.7 1632 ./super-test.sh tmpdir capnp-gcc-4.7 quick
linux-gcc-4.8 1633 ./super-test.sh tmpdir capnp-gcc-4.8 quick gcc-4.8 linux-gcc-4.8 1635 ./super-test.sh tmpdir capnp-gcc-4.8 quick gcc-4.8
linux-clang 1650 ./super-test.sh tmpdir capnp-clang quick clang linux-clang 1652 ./super-test.sh tmpdir capnp-clang quick clang
mac 758 ./super-test.sh remote beat caffeinate quick mac 758 ./super-test.sh remote beat caffeinate quick
cygwin 769 ./super-test.sh remote Kenton@flashman quick cygwin 769 ./super-test.sh remote Kenton@flashman quick
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment