Commit 6beb5910 authored by Kenton Varda's avatar Kenton Varda

Work around OSX and Cygwin signal issues.

parent b483b77b
...@@ -45,7 +45,10 @@ inline void delay() { usleep(10000); } ...@@ -45,7 +45,10 @@ inline void delay() { usleep(10000); }
class AsyncUnixTest: public testing::Test { class AsyncUnixTest: public testing::Test {
public: public:
static void SetUpTestCase() { static void SetUpTestCase() {
UnixEventPort::captureSignal(SIGUSR2); // We use SIGIO and SIGURG as our test signals because they're two signals that we can be
// reasonably confident won't otherwise be delivered to any KJ or Cap'n Proto test. We can't
// use SIGUSR1 because it is reserved by UnixEventPort and SIGUSR2 is used by Valgrind on OSX.
UnixEventPort::captureSignal(SIGURG);
UnixEventPort::captureSignal(SIGIO); UnixEventPort::captureSignal(SIGIO);
} }
}; };
...@@ -55,10 +58,10 @@ TEST_F(AsyncUnixTest, Signals) { ...@@ -55,10 +58,10 @@ TEST_F(AsyncUnixTest, Signals) {
EventLoop loop(port); EventLoop loop(port);
WaitScope waitScope(loop); WaitScope waitScope(loop);
kill(getpid(), SIGUSR2); kill(getpid(), SIGURG);
siginfo_t info = port.onSignal(SIGUSR2).wait(waitScope); siginfo_t info = port.onSignal(SIGURG).wait(waitScope);
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGURG, info.si_signo);
EXPECT_SI_CODE(SI_USER, info.si_code); EXPECT_SI_CODE(SI_USER, info.si_code);
} }
...@@ -66,7 +69,7 @@ TEST_F(AsyncUnixTest, Signals) { ...@@ -66,7 +69,7 @@ TEST_F(AsyncUnixTest, Signals) {
TEST_F(AsyncUnixTest, SignalWithValue) { TEST_F(AsyncUnixTest, SignalWithValue) {
// This tests that if we use sigqueue() to attach a value to the signal, that value is received // This tests that if we use sigqueue() to attach a value to the signal, that value is received
// correctly. Note that this only works on platforms that support real-time signals -- even // correctly. Note that this only works on platforms that support real-time signals -- even
// though the signal we're sending is SIGUSR2, the sigqueue() system call is introduced by RT // though the signal we're sending is SIGURG, the sigqueue() system call is introduced by RT
// signals. Hence this test won't run on e.g. Mac OSX. // signals. Hence this test won't run on e.g. Mac OSX.
UnixEventPort port; UnixEventPort port;
...@@ -76,10 +79,10 @@ TEST_F(AsyncUnixTest, SignalWithValue) { ...@@ -76,10 +79,10 @@ TEST_F(AsyncUnixTest, SignalWithValue) {
union sigval value; union sigval value;
memset(&value, 0, sizeof(value)); memset(&value, 0, sizeof(value));
value.sival_int = 123; value.sival_int = 123;
sigqueue(getpid(), SIGUSR2, value); sigqueue(getpid(), SIGURG, value);
siginfo_t info = port.onSignal(SIGUSR2).wait(waitScope); siginfo_t info = port.onSignal(SIGURG).wait(waitScope);
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGURG, info.si_signo);
EXPECT_SI_CODE(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);
} }
...@@ -96,23 +99,28 @@ TEST_F(AsyncUnixTest, SignalsMultiListen) { ...@@ -96,23 +99,28 @@ TEST_F(AsyncUnixTest, SignalsMultiListen) {
ADD_FAILURE() << kj::str(exception).cStr(); ADD_FAILURE() << kj::str(exception).cStr();
}); });
kill(getpid(), SIGUSR2); kill(getpid(), SIGURG);
siginfo_t info = port.onSignal(SIGUSR2).wait(waitScope); siginfo_t info = port.onSignal(SIGURG).wait(waitScope);
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGURG, info.si_signo);
EXPECT_SI_CODE(SI_USER, info.si_code); EXPECT_SI_CODE(SI_USER, info.si_code);
} }
#if !__CYGWIN32__
// Cygwin32 (but not Cygwin64) appears not to deliver SIGURG in the following test (but it does
// deliver SIGIO, if you reverse the order of the waits). Since this doesn't occur on any other
// platform I'm assuming it's a Cygwin bug.
TEST_F(AsyncUnixTest, SignalsMultiReceive) { TEST_F(AsyncUnixTest, SignalsMultiReceive) {
UnixEventPort port; UnixEventPort port;
EventLoop loop(port); EventLoop loop(port);
WaitScope waitScope(loop); WaitScope waitScope(loop);
kill(getpid(), SIGUSR2); kill(getpid(), SIGURG);
kill(getpid(), SIGIO); kill(getpid(), SIGIO);
siginfo_t info = port.onSignal(SIGUSR2).wait(waitScope); siginfo_t info = port.onSignal(SIGURG).wait(waitScope);
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGURG, info.si_signo);
EXPECT_SI_CODE(SI_USER, info.si_code); EXPECT_SI_CODE(SI_USER, info.si_code);
info = port.onSignal(SIGIO).wait(waitScope); info = port.onSignal(SIGIO).wait(waitScope);
...@@ -120,6 +128,8 @@ TEST_F(AsyncUnixTest, SignalsMultiReceive) { ...@@ -120,6 +128,8 @@ TEST_F(AsyncUnixTest, SignalsMultiReceive) {
EXPECT_SI_CODE(SI_USER, info.si_code); EXPECT_SI_CODE(SI_USER, info.si_code);
} }
#endif // !__CYGWIN32__
TEST_F(AsyncUnixTest, SignalsAsync) { TEST_F(AsyncUnixTest, SignalsAsync) {
UnixEventPort port; UnixEventPort port;
EventLoop loop(port); EventLoop loop(port);
...@@ -129,16 +139,21 @@ TEST_F(AsyncUnixTest, SignalsAsync) { ...@@ -129,16 +139,21 @@ TEST_F(AsyncUnixTest, SignalsAsync) {
pthread_t mainThread = pthread_self(); pthread_t mainThread = pthread_self();
Thread thread([&]() { Thread thread([&]() {
delay(); delay();
pthread_kill(mainThread, SIGUSR2); pthread_kill(mainThread, SIGURG);
}); });
siginfo_t info = port.onSignal(SIGUSR2).wait(waitScope); siginfo_t info = port.onSignal(SIGURG).wait(waitScope);
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGURG, info.si_signo);
#if __linux__ #if __linux__
EXPECT_SI_CODE(SI_TKILL, info.si_code); EXPECT_SI_CODE(SI_TKILL, info.si_code);
#endif #endif
} }
#if !__CYGWIN32__
// Cygwin32 (but not Cygwin64) appears not to deliver SIGURG in the following test (but it does
// deliver SIGIO, if you reverse the order of the waits). Since this doesn't occur on any other
// platform I'm assuming it's a Cygwin bug.
TEST_F(AsyncUnixTest, SignalsNoWait) { TEST_F(AsyncUnixTest, SignalsNoWait) {
// Verify that UnixEventPort::poll() correctly receives pending signals. // Verify that UnixEventPort::poll() correctly receives pending signals.
...@@ -146,11 +161,11 @@ TEST_F(AsyncUnixTest, SignalsNoWait) { ...@@ -146,11 +161,11 @@ TEST_F(AsyncUnixTest, SignalsNoWait) {
EventLoop loop(port); EventLoop loop(port);
WaitScope waitScope(loop); WaitScope waitScope(loop);
bool receivedSigusr2 = false; bool receivedSigurg = false;
bool receivedSigio = false; bool receivedSigio = false;
port.onSignal(SIGUSR2).then([&](siginfo_t&& info) { port.onSignal(SIGURG).then([&](siginfo_t&& info) {
receivedSigusr2 = true; receivedSigurg = true;
EXPECT_EQ(SIGUSR2, info.si_signo); EXPECT_EQ(SIGURG, info.si_signo);
EXPECT_SI_CODE(SI_USER, info.si_code); EXPECT_SI_CODE(SI_USER, info.si_code);
}).detach([](Exception&& e) { ADD_FAILURE() << str(e).cStr(); }); }).detach([](Exception&& e) { ADD_FAILURE() << str(e).cStr(); });
port.onSignal(SIGIO).then([&](siginfo_t&& info) { port.onSignal(SIGIO).then([&](siginfo_t&& info) {
...@@ -159,28 +174,30 @@ TEST_F(AsyncUnixTest, SignalsNoWait) { ...@@ -159,28 +174,30 @@ TEST_F(AsyncUnixTest, SignalsNoWait) {
EXPECT_SI_CODE(SI_USER, info.si_code); EXPECT_SI_CODE(SI_USER, info.si_code);
}).detach([](Exception&& e) { ADD_FAILURE() << str(e).cStr(); }); }).detach([](Exception&& e) { ADD_FAILURE() << str(e).cStr(); });
kill(getpid(), SIGUSR2); kill(getpid(), SIGURG);
kill(getpid(), SIGIO); kill(getpid(), SIGIO);
EXPECT_FALSE(receivedSigusr2); EXPECT_FALSE(receivedSigurg);
EXPECT_FALSE(receivedSigio); EXPECT_FALSE(receivedSigio);
loop.run(); loop.run();
EXPECT_FALSE(receivedSigusr2); EXPECT_FALSE(receivedSigurg);
EXPECT_FALSE(receivedSigio); EXPECT_FALSE(receivedSigio);
port.poll(); port.poll();
EXPECT_FALSE(receivedSigusr2); EXPECT_FALSE(receivedSigurg);
EXPECT_FALSE(receivedSigio); EXPECT_FALSE(receivedSigio);
loop.run(); loop.run();
EXPECT_TRUE(receivedSigusr2); EXPECT_TRUE(receivedSigurg);
EXPECT_TRUE(receivedSigio); EXPECT_TRUE(receivedSigio);
} }
#endif // !__CYGWIN32__
TEST_F(AsyncUnixTest, Poll) { TEST_F(AsyncUnixTest, Poll) {
UnixEventPort port; UnixEventPort port;
EventLoop loop(port); EventLoop loop(port);
......
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