From 1463958dbbcd51edf670930aa17b78514b44a906 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net>
Date: Sun, 21 Mar 2021 07:36:11 -0400
Subject: [PATCH] A poll() failure with EINTR does not mean a socket is closed.

This won't impact Synchronet as it has a separate signal handling
thread, but we still need to behave properly for processes that
don't.  I'm also saying that ENOMEM does not indicate a disconnection,
though it may be better to pretend it was disconnected...
---
 src/xpdev/sockwrap.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/src/xpdev/sockwrap.c b/src/xpdev/sockwrap.c
index e0abe84747..6945e7daf4 100644
--- a/src/xpdev/sockwrap.c
+++ b/src/xpdev/sockwrap.c
@@ -362,6 +362,12 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout)
 		if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL))
 			return FALSE;
 	}
+
+	if (j == -1) {
+		if (errno == EINTR || errno == ENOMEM)
+			return TRUE;
+	}
+
 	return FALSE;
 #endif
 }
@@ -489,10 +495,15 @@ BOOL socket_recvdone(SOCKET sock, int timeout)
 	pfd.fd = sock;
 	pfd.events = POLLIN;
 
-	if (poll(&pfd, 1, timeout) == 1) {
-		if (pfd.revents & POLLIN)
-			return FALSE;
-		return TRUE;
+	switch (poll(&pfd, 1, timeout)) {
+		case 1:
+			if (pfd.revents & POLLIN)
+				return FALSE;
+			return TRUE;
+		case -1:
+			if (errno == EINTR || errno == ENOMEM)
+				return FALSE;
+			return TRUE;
 	}
 	return FALSE;
 #endif
-- 
GitLab