1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 17:07:34 +00:00

LibCore: Don't crash in IPC client/server on EAGAIN

Instead, just sched_yield() and try again. This makes the WindowServer
not fall apart whenever clients take a bit too long to respond.

Fixes #656.
This commit is contained in:
Andreas Kling 2019-10-14 21:47:59 +02:00
parent 735f02900b
commit 7dbc13ac88
2 changed files with 34 additions and 19 deletions

View file

@ -6,6 +6,7 @@
#include <LibCore/CNotifier.h> #include <LibCore/CNotifier.h>
#include <LibCore/CSyscallUtils.h> #include <LibCore/CSyscallUtils.h>
#include <LibIPC/IMessage.h> #include <LibIPC/IMessage.h>
#include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/select.h> #include <sys/select.h>
@ -145,10 +146,19 @@ namespace Client {
++iov_count; ++iov_count;
} }
int nwritten = writev(m_connection->fd(), iov, iov_count); int nwritten;
if (nwritten < 0) {
perror("writev"); for (;;) {
ASSERT_NOT_REACHED(); nwritten = writev(m_connection->fd(), iov, iov_count);
if (nwritten < 0) {
if (errno == EAGAIN) {
sched_yield();
continue;
}
perror("writev");
ASSERT_NOT_REACHED();
}
break;
} }
ASSERT((size_t)nwritten == sizeof(message) + extra_data.size()); ASSERT((size_t)nwritten == sizeof(message) + extra_data.size());

View file

@ -8,8 +8,8 @@
#include <LibCore/CObject.h> #include <LibCore/CObject.h>
#include <LibIPC/IEndpoint.h> #include <LibIPC/IEndpoint.h>
#include <LibIPC/IMessage.h> #include <LibIPC/IMessage.h>
#include <errno.h> #include <errno.h>
#include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
@ -104,21 +104,26 @@ namespace Server {
++iov_count; ++iov_count;
} }
int nwritten = writev(m_socket->fd(), iov, iov_count); int nwritten = 0;
if (nwritten < 0) { for (;;) {
switch (errno) { nwritten = writev(m_socket->fd(), iov, iov_count);
case EPIPE: if (nwritten < 0) {
dbgprintf("Connection::post_message: Disconnected from peer.\n"); switch (errno) {
shutdown(); case EPIPE:
return; dbgprintf("Connection::post_message: Disconnected from peer.\n");
case EAGAIN: shutdown();
dbgprintf("Connection::post_message: Client buffer overflowed.\n"); return;
did_misbehave(); case EAGAIN:
return; // FIXME: It would be better to push these onto a queue so we can go back
default: // to servicing other clients.
perror("Connection::post_message writev"); sched_yield();
ASSERT_NOT_REACHED(); continue;
default:
perror("Connection::post_message writev");
ASSERT_NOT_REACHED();
}
} }
break;
} }
ASSERT(nwritten == (int)(sizeof(message) + extra_data.size())); ASSERT(nwritten == (int)(sizeof(message) + extra_data.size()));