From e3ad4e132dae2a647533ea2de9b10fba9ae94656 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net>
Date: Sun, 21 Mar 2021 17:30:25 -0400
Subject: [PATCH] We still need to peek a byte to tell that recv is done with
 poll()

Not all implementations set POLLHUP when a TCP socket is half-closed.
---
 src/xpdev/sockwrap.c | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/src/xpdev/sockwrap.c b/src/xpdev/sockwrap.c
index 8ef9cec97f..a2e2a2cae9 100644
--- a/src/xpdev/sockwrap.c
+++ b/src/xpdev/sockwrap.c
@@ -330,7 +330,8 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout)
 	return(FALSE);
 #else
 	struct pollfd pfd = {0};
-	int j;
+	int j, rd;
+	char ch;
 
 	if(rd_p!=NULL)
 		*rd_p=FALSE;
@@ -342,7 +343,7 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout)
 		return(FALSE);
 
 	pfd.fd = sock;
-	pfd.events = POLLIN;
+	pfd.events = POLLIN | POLLHUP;
 	if (wr_p != NULL)
 		pfd.events |= POLLOUT;
 
@@ -354,13 +355,21 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout)
 	if (j == 1) {
 		if (wr_p != NULL && (pfd.revents & POLLOUT))
 			*wr_p = TRUE;
-		if (rd_p != NULL && (pfd.revents & POLLIN)) {
+		if (rd_p != NULL && (pfd.revents & POLLIN))
 			*rd_p = TRUE;
-			return TRUE;
-		}
 
-		if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL))
+		if (pfd.revents & (POLLERR | POLLNVAL))
+			return FALSE;
+
+		if(pfd.revents & (POLLIN | POLLHUP) && (rd_p !=NULL || wr_p==NULL))  {
+			rd=recv(sock,&ch,1,MSG_PEEK);
+			if(rd==1 || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE)) {
+				if(rd_p!=NULL)
+					*rd_p=TRUE;
+				return(TRUE);
+			}
 			return FALSE;
+		}
 	}
 
 	if (j == -1) {
@@ -495,12 +504,18 @@ BOOL socket_recvdone(SOCKET sock, int timeout)
 	struct pollfd pfd = {0};
 	pfd.fd = sock;
 	pfd.events = POLLIN;
+	char ch;
+	int rd;
 
 	switch (poll(&pfd, 1, timeout)) {
 		case 1:
-			if (pfd.revents & POLLIN)
-				return FALSE;
-			return TRUE;
+			if (pfd.revents & (POLLIN | POLLHUP)) {
+				rd = recv(sock,&ch,1,MSG_PEEK);
+				if (rd == 1 || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE))
+					return FALSE;
+				return TRUE;
+			}
+			return FALSE;
 		case -1:
 			if (errno == EINTR || errno == ENOMEM)
 				return FALSE;
-- 
GitLab