From a8864dc5900a877d621415d0601da651ee4ece63 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 20 May 2019 01:18:33 +0200 Subject: [PATCH] Kernel: Report EAGAIN from read() on a non-blocking socket if the buffer is empty This is not EOF, and never should have been so -- can trip up other code when porting. Also updates LibGUI and WindowServer which both relied on the old behaviour (and didn't work without changes). There may be others, but I didn't run into them with a quick inspection. --- Kernel/Net/LocalSocket.cpp | 14 ++++++++++++-- LibGUI/GEventLoop.cpp | 15 +++++++-------- Servers/WindowServer/WSEventLoop.cpp | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp index 28ab02439fd..e0887103d65 100644 --- a/Kernel/Net/LocalSocket.cpp +++ b/Kernel/Net/LocalSocket.cpp @@ -153,10 +153,20 @@ bool LocalSocket::can_read(FileDescriptor& descriptor) const ssize_t LocalSocket::read(FileDescriptor& descriptor, byte* buffer, ssize_t size) { auto role = descriptor.socket_role(); - if (role == SocketRole::Accepted) + if (role == SocketRole::Accepted) { + if (!descriptor.is_blocking()) { + if (m_for_server.is_empty()) + return -EAGAIN; + } return m_for_server.read(buffer, size); - if (role == SocketRole::Connected) + } + if (role == SocketRole::Connected) { + if (!descriptor.is_blocking()) { + if (m_for_client.is_empty()) + return -EAGAIN; + } return m_for_client.read(buffer, size); + } ASSERT_NOT_REACHED(); } diff --git a/LibGUI/GEventLoop.cpp b/LibGUI/GEventLoop.cpp index ba29e4e916e..7999c88e49c 100644 --- a/LibGUI/GEventLoop.cpp +++ b/LibGUI/GEventLoop.cpp @@ -324,22 +324,22 @@ void GEventLoop::process_unprocessed_bundles() bool GEventLoop::drain_messages_from_server() { - bool is_first_pass = true; for (;;) { WSAPI_ServerMessage message; ssize_t nread = read(s_windowserver_fd, &message, sizeof(WSAPI_ServerMessage)); if (nread < 0) { + if (errno == EAGAIN) { + return true; + } perror("read"); quit(1); return false; } if (nread == 0) { - if (is_first_pass) { - fprintf(stderr, "EOF on WindowServer fd\n"); - quit(1); - return false; - } - return true; + fprintf(stderr, "EOF on WindowServer fd\n"); + quit(1); + exit(-1); + return false; } assert(nread == sizeof(message)); ByteBuffer extra_data; @@ -355,7 +355,6 @@ bool GEventLoop::drain_messages_from_server() ASSERT(extra_nread == message.extra_size); } m_unprocessed_bundles.append({ move(message), move(extra_data) }); - is_first_pass = false; } } diff --git a/Servers/WindowServer/WSEventLoop.cpp b/Servers/WindowServer/WSEventLoop.cpp index 904dfca2fc2..c2fe108b6fe 100644 --- a/Servers/WindowServer/WSEventLoop.cpp +++ b/Servers/WindowServer/WSEventLoop.cpp @@ -301,7 +301,7 @@ void WSEventLoop::drain_client(WSClientConnection& client) WSAPI_ClientMessage message; // FIXME: Don't go one message at a time, that's so much context switching, oof. ssize_t nread = read(client.fd(), &message, sizeof(WSAPI_ClientMessage)); - if (nread == 0) { + if (nread == 0 || (nread == -1 && errno == EAGAIN)) { if (!messages_received) post_event(client, make(client.client_id())); break;