瀏覽代碼

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.
Andreas Kling 5 年之前
父節點
當前提交
7dbc13ac88
共有 2 個文件被更改,包括 34 次插入19 次删除
  1. 14 4
      Libraries/LibCore/CoreIPCClient.h
  2. 20 15
      Libraries/LibCore/CoreIPCServer.h

+ 14 - 4
Libraries/LibCore/CoreIPCClient.h

@@ -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());
 

+ 20 - 15
Libraries/LibCore/CoreIPCServer.h

@@ -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()));