Commit 7ba69d69 authored by Oliver Kuckertz's avatar Oliver Kuckertz

Fix FdObserver::whenUrgentDataAvailable test getting stuck on OS X

parent 4021ba9b
...@@ -455,18 +455,17 @@ TEST(AsyncUnixTest, WriteObserver) { ...@@ -455,18 +455,17 @@ TEST(AsyncUnixTest, WriteObserver) {
EXPECT_TRUE(writable); EXPECT_TRUE(writable);
} }
#ifdef __linux__
TEST(AsyncUnixTest, UrgentObserver) { TEST(AsyncUnixTest, UrgentObserver) {
// Verify that FdObserver correctly detects availability of out-of-band data. // Verify that FdObserver correctly detects availability of out-of-band data.
// Availability of out-of-band data is implementation-specific. // Availability of out-of-band data is implementation-specific.
// Linux's TCP/IP stack supports out-of-band messages for TCP sockets, which is used for this // Linux's and OS X's TCP/IP stack supports out-of-band messages for TCP sockets, which is used
// test. Other platforms appear to lack generally available interfaces that could be used for // for this test.
// generating a POLLPRI event, so we disable the test for all platforms but Linux.
UnixEventPort port; UnixEventPort port;
EventLoop loop(port); EventLoop loop(port);
WaitScope waitScope(loop); WaitScope waitScope(loop);
int tmpFd; int tmpFd;
char c;
// Spawn a TCP server on localhost:44444 // Spawn a TCP server on localhost:44444
KJ_SYSCALL(tmpFd = socket(AF_INET, SOCK_STREAM, 0)); KJ_SYSCALL(tmpFd = socket(AF_INET, SOCK_STREAM, 0));
...@@ -475,34 +474,53 @@ TEST(AsyncUnixTest, UrgentObserver) { ...@@ -475,34 +474,53 @@ TEST(AsyncUnixTest, UrgentObserver) {
saddr.sin_family = AF_INET; saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
saddr.sin_port = htons(44444); saddr.sin_port = htons(44444);
int optval = 1;
KJ_SYSCALL(setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
KJ_SYSCALL(bind(serverFd, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr))); KJ_SYSCALL(bind(serverFd, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr)));
KJ_SYSCALL(listen(serverFd, 1)); KJ_SYSCALL(listen(serverFd, 1));
// Accept one connection, send one OOB message, wait for a response // Accept one connection, send in-band and OOB byte, wait for a quit message
Thread thread([&]() { Thread thread([&]() {
int tmpFd;
char c;
sockaddr_in caddr; sockaddr_in caddr;
socklen_t caddrLen = sizeof(caddr); socklen_t caddrLen = sizeof(caddr);
int tmpFd;
KJ_SYSCALL(tmpFd = accept(serverFd, reinterpret_cast<sockaddr*>(&caddr), &caddrLen)); KJ_SYSCALL(tmpFd = accept(serverFd, reinterpret_cast<sockaddr*>(&caddr), &caddrLen));
kj::AutoCloseFd clientFd(tmpFd); kj::AutoCloseFd clientFd(tmpFd);
delay(); delay();
char c = 'x';
// Workaround: OS X won't signal POLLPRI without POLLIN. Also enqueue some in-band data.
c = 'i';
KJ_SYSCALL(send(clientFd, &c, 1, 0));
c = 'o';
KJ_SYSCALL(send(clientFd, &c, 1, MSG_OOB)); KJ_SYSCALL(send(clientFd, &c, 1, MSG_OOB));
KJ_SYSCALL(recv(clientFd, &c, 1, 0)); KJ_SYSCALL(recv(clientFd, &c, 1, 0));
EXPECT_EQ('q', c);
}); });
KJ_SYSCALL(tmpFd = socket(AF_INET, SOCK_STREAM, 0)); KJ_SYSCALL(tmpFd = socket(AF_INET, SOCK_STREAM, 0));
kj::AutoCloseFd clientFd(tmpFd); kj::AutoCloseFd clientFd(tmpFd);
UnixEventPort::FdObserver observer(port, clientFd, UnixEventPort::FdObserver::OBSERVE_URGENT);
KJ_SYSCALL(connect(clientFd, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr))); KJ_SYSCALL(connect(clientFd, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr)));
UnixEventPort::FdObserver observer(port, clientFd,
UnixEventPort::FdObserver::OBSERVE_READ | UnixEventPort::FdObserver::OBSERVE_URGENT);
// Attempt to read the urgent byte prior to reading the in-band byte.
observer.whenUrgentDataAvailable().wait(waitScope); observer.whenUrgentDataAvailable().wait(waitScope);
KJ_SYSCALL(recv(clientFd, &c, 1, MSG_OOB));
EXPECT_EQ('o', c);
// Dummy message for unblocking the server thread // Ensure that the in-band byte is still in the queue and makes the socket readable.
char c = 'x'; observer.whenBecomesReadable().wait(waitScope);
KJ_SYSCALL(recv(clientFd, &c, 1, 0));
EXPECT_EQ('i', c);
// Allow server thread to let its clientFd go out of scope.
c = 'q';
KJ_SYSCALL(send(clientFd, &c, 1, 0)); KJ_SYSCALL(send(clientFd, &c, 1, 0));
} }
#endif
TEST(AsyncUnixTest, SteadyTimers) { TEST(AsyncUnixTest, SteadyTimers) {
captureSignals(); captureSignals();
......
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