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 {
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 {
public:
void taskFailed(kj::Exception&& exception) override {
......@@ -56,7 +63,7 @@ TEST_F(AsyncUnixTest, Signals) {
siginfo_t info = loop.wait(loop.onSignal(SIGUSR2));
EXPECT_EQ(SIGUSR2, info.si_signo);
EXPECT_EQ(SI_USER, info.si_code);
EXPECT_SI_CODE(SI_USER, info.si_code);
}
#ifdef SIGRTMIN
......@@ -74,7 +81,7 @@ TEST_F(AsyncUnixTest, SignalWithValue) {
siginfo_t info = loop.wait(loop.onSignal(SIGUSR2));
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);
}
#endif
......@@ -92,7 +99,7 @@ TEST_F(AsyncUnixTest, SignalsMulti) {
siginfo_t info = loop.wait(loop.onSignal(SIGUSR2));
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) {
......@@ -110,14 +117,14 @@ TEST_F(AsyncUnixTest, SignalsAsync) {
[&](siginfo_t&& info) {
received = true;
EXPECT_EQ(SIGUSR2, info.si_signo);
EXPECT_EQ(SI_USER, info.si_code);
EXPECT_SI_CODE(SI_TKILL, info.si_code);
});
delay();
EXPECT_FALSE(received);
kill(getpid(), SIGUSR2);
thread.sendSignal(SIGUSR2);
SimpleEventLoop mainLoop;
mainLoop.wait(kj::mv(promise));
......
......@@ -469,15 +469,22 @@ void UnixEventLoop::sleep() {
sigset_t origMask;
sigprocmask(SIG_UNBLOCK, &newMask, &origMask);
int pollResult = poll(pollfds.begin(), pollfds.size(), -1);
int error = pollResult < 0 ? errno : 0;
int pollResult;
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);
threadCapture = nullptr;
__atomic_store_n(&isSleeping, false, __ATOMIC_RELAXED);
if (pollResult < 0) {
KJ_FAIL_SYSCALL("poll()", error);
KJ_FAIL_SYSCALL("poll()", pollError);
}
for (auto i: indices(pollfds)) {
......
......@@ -24,6 +24,7 @@
#include "thread.h"
#include "debug.h"
#include <pthread.h>
#include <signal.h>
namespace kj {
......@@ -39,7 +40,17 @@ Thread::Thread(void* (*run)(void*), void (*deleteArg)(void*), void* arg) {
}
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
......@@ -40,6 +40,9 @@ public:
~Thread();
void sendSignal(int signo);
// Send a Unix signal to the given thread, using pthread_kill or an equivalent.
private:
unsigned long long threadId; // actually pthread_t
......
linux-gcc-4.7 1630 ./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-clang 1650 ./super-test.sh tmpdir capnp-clang quick clang
linux-gcc-4.7 1632 ./super-test.sh tmpdir capnp-gcc-4.7 quick
linux-gcc-4.8 1635 ./super-test.sh tmpdir capnp-gcc-4.8 quick gcc-4.8
linux-clang 1652 ./super-test.sh tmpdir capnp-clang quick clang
mac 758 ./super-test.sh remote beat caffeinate 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