From 80d800e6d4138f75bc22119ad6d4a6bb427b52e4 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 3 Jul 2020 13:56:48 +0200 Subject: [PATCH] LibIPC: Don't assert on short writes in IPC::ClientConnection This stops servers from crashing when a client's socket buffer becomes full and we can't post any more messages to it. Normally this means the client process is hanged/spinning, but I suppose this could also happen under severe system load. It's unclear to me what a better solution here would be. We can't keep buffering messages indefinitely if the client is just never going to receive them anyway. At some point we have to cut our losses, and it seems pretty reasonable to let the kernel socket buffer be the cutoff. It will be the responsibility of the individual server implementations to avoid sending messages to clients that may be unable to handle them. --- Libraries/LibIPC/ClientConnection.h | 36 +++++++++++++++-------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Libraries/LibIPC/ClientConnection.h b/Libraries/LibIPC/ClientConnection.h index ed7a76ee31..78b6b6c3d8 100644 --- a/Libraries/LibIPC/ClientConnection.h +++ b/Libraries/LibIPC/ClientConnection.h @@ -112,26 +112,28 @@ public: auto buffer = message.encode(); - int nwritten = write(m_socket->fd(), buffer.data(), buffer.size()); - if (nwritten < 0) { - switch (errno) { - case EPIPE: - dbg() << *this << "::post_message: Disconnected from peer"; - shutdown(); - return; - case EAGAIN: - dbg() << *this << "::post_message: Client buffer overflowed."; - did_misbehave(); - return; - default: - perror("Connection::post_message write"); - shutdown(); - return; + auto bytes_remaining = buffer.size(); + while (bytes_remaining) { + auto nwritten = write(m_socket->fd(), buffer.data(), buffer.size()); + if (nwritten < 0) { + switch (errno) { + case EPIPE: + dbg() << *this << "::post_message: Disconnected from peer"; + shutdown(); + return; + case EAGAIN: + dbg() << *this << "::post_message: Client buffer overflowed."; + did_misbehave(); + return; + default: + perror("Connection::post_message write"); + shutdown(); + return; + } } + bytes_remaining -= nwritten; } - ASSERT(static_cast(nwritten) == buffer.size()); - m_responsiveness_timer->start(); }