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.
This commit is contained in:
Andreas Kling 2020-07-03 13:56:48 +02:00
parent a98712035c
commit 80d800e6d4
Notes: sideshowbarker 2024-07-19 05:13:36 +09:00

View File

@ -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<size_t>(nwritten) == buffer.size());
m_responsiveness_timer->start();
}