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
Notes: sideshowbarker 2024-07-19 11:41:47 +09:00
2 changed files with 34 additions and 19 deletions

View File

@ -6,6 +6,7 @@
#include <LibCore/CNotifier.h>
#include <LibCore/CSyscallUtils.h>
#include <LibIPC/IMessage.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
@ -145,10 +146,19 @@ namespace Client {
++iov_count;
}
int nwritten = writev(m_connection->fd(), iov, iov_count);
if (nwritten < 0) {
perror("writev");
ASSERT_NOT_REACHED();
int nwritten;
for (;;) {
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());

View File

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