* net: improved poll revent handling
authorUrban Wallasch <urban.wallasch@freenet.de>
Wed, 23 Oct 2019 11:57:33 +0000 (13:57 +0200)
committerUrban Wallasch <urban.wallasch@freenet.de>
Wed, 23 Oct 2019 11:57:33 +0000 (13:57 +0200)
net/net.c

index 83c188e2ba35711d0896b1e97f523728aac202fe..9cbf3a274aa4f140243189f2a53df21d8f0dac7e 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -244,35 +244,47 @@ int net_close(int sock) {
 
 /* Wait for and accept a TCP connection request: */
 int tcp_accept(int sock, int timeout) {
-    int pr, conn = -1;
+    int r;
     struct pollfd pfd;
-    uint8_t a_[128];
-    struct sockaddr *addr = (void *)a_;
-    socklen_t addrlen = sizeof a_;
 
     pfd.fd = sock;
     pfd.events = POLLIN;
-    pr = poll(&pfd, 1, timeout);
-    if (pr == 1 && pfd.revents == POLLIN) {
-        conn = accept(sock, addr, &addrlen);
-        GET_STRADDR(straddr_, addr, addrlen);
-        if (conn < 0) {
-            NETLOG_ERR(EAI_SYSTEM, "accept(%d, %s)", sock, straddr_);
-        } else {
-            NETLOG_DBG("accept(%d) -> (%d, %s): Ok", sock, conn, straddr_);
+    r = poll(&pfd, 1, timeout);
+    if (r == 1 && pfd.revents & (POLLIN | POLLERR | POLLHUP)) {
+        /* In case of POLLERR or POLLHUP we let accept() catch the error! */
+        unsigned char a_[128];
+        struct sockaddr *addr = (void *)a_;
+        socklen_t addrlen = sizeof a_;
+        r = accept(sock, addr, &addrlen);
+        if (r < 0) {
+            r = EAI_SYSTEM;
+        }
+        else {
+            GET_STRADDR(straddr_, addr, addrlen);
+            NETLOG_DBG("accept(%d) -> (%d, %s): Ok", sock, r, straddr_);
+            FREE_STRADDR(straddr_);
         }
-        FREE_STRADDR(straddr_);
-    }
-    else if (pr < 0) {
-        NETLOG_ERR(EAI_SYSTEM, "poll(%d, %d)", sock, timeout);
-        return EAI_SYSTEM;
     }
-    else if (pr == 0) {
-        NETLOG_DBG("poll(%d, %d): Timeout", sock, timeout);
+    else if (r == 0) {
         errno = ETIMEDOUT;
-        return EAI_SYSTEM;
+        r = EAI_SYSTEM;
+    }
+    else if (r < 0) {
+        r = EAI_SYSTEM;
+    }
+    else if (pfd.revents & POLLNVAL) {
+        errno = EBADF;
+        r = EAI_SYSTEM;
+    }
+    else {
+        NETLOG_DBG("This should never happen! (r=%d, revents=%hd)", r, pfd.revents);
+        errno = EIO;
+        r = EAI_SYSTEM;
+    }
+    if (r < 0) {
+        NETLOG_ERR(r, "tcp_accept(%d)", sock);
     }
-    return conn < 0 ? EAI_SYSTEM : conn;
+    return r;
 }
 
 /* Copy textual description of last error to user supplied buffer: */