From 1773233beb1ec49055d8127394bdfbcb626949f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net>
Date: Mon, 5 Apr 2021 05:55:02 -0400
Subject: [PATCH] More closely reproduce select() behaviour when using poll()

Specifically, have errors mean the fd is "ready".

Also, fix some extra revent clearing and a spy socket issue while
we're looking at this code.

Should fix issues with CGI scripts that close stdin/stdout but do
not terminate, and maybe deal with some other corner cases at the
same time.
---
 src/sbbs3/main.cpp    |  6 ++----
 src/sbbs3/services.c  |  2 +-
 src/sbbs3/websrvr.c   | 10 +++++-----
 src/sbbs3/xtrn.cpp    |  5 ++---
 src/xpdev/multisock.c |  2 +-
 src/xpdev/sockwrap.c  |  4 ++--
 6 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 3c7bbf84cc..e5b6d9874a 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -1931,12 +1931,10 @@ void input_thread(void *arg)
 #ifdef PREFER_POLL
 		fds[0].fd = sbbs->client_socket;
 		fds[0].events = POLLIN;
-		fds[0].revents = 0;
 		nfds = 1;
 		if (uspy_socket[sbbs->cfg.node_num-1] != INVALID_SOCKET) {
-			fds[0].fd = uspy_socket[sbbs->cfg.node_num-1];
-			fds[0].events = POLLIN;
-			fds[0].revents = 0;
+			fds[1].fd = uspy_socket[sbbs->cfg.node_num-1];
+			fds[1].events = POLLIN;
 			nfds++;
 		}
 
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 59556cad58..dbdb4aabd2 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -2083,7 +2083,7 @@ void services_thread(void* arg)
 					continue;
 
 				for(j=0; j<service[i].set->sock_count; j++) {
-					if ((fds[nfdsi + j].revents & POLLIN) == 0)
+					if ((fds[nfdsi + j].revents) == 0)
 						continue;
 #else
 			/* Setup select() parms */
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 162dd66389..5fbe1a9238 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -4192,9 +4192,9 @@ static int cgi_read_wait_timeout(void *arg)
 	cd->fds[1].events = POLLIN;
 
 	if (poll(cd->fds, 2, startup->max_cgi_inactivity * 1000) > 0)  {
-		if (cd->fds[0].revents & POLLIN)
+		if (cd->fds[0].revents)
 			ret |= CGI_OUTPUT_READY;
-		if (cd->fds[1].revents & POLLIN)
+		if (cd->fds[1].revents)
 			ret |= CGI_ERROR_READY;
 	}
 
@@ -4778,7 +4778,7 @@ static BOOL exec_cgi(http_session_t *session)
 		cd.fds[0].events = POLLOUT;
 		while(sent < session->req.post_len) {
 			if (poll(cd.fds, 1, 1000) > 0) {
-				if (cd.fds[0].revents & POLLIN)
+				if (cd.fds[0].revents)
 					i = write(in_pipe[1], &session->req.post_data[sent], session->req.post_len - sent);
 				else
 					i = 0;
@@ -4835,7 +4835,7 @@ static BOOL exec_cgi(http_session_t *session)
 		close(in_pipe[1]);	/* close excess file descriptor */
 	/* Drain STDERR & STDOUT */
 	while(poll(cd.fds, 2, 1000) > 0) {
-		if(cd.fds[1].revents & POLLIN) {
+		if(cd.fds[1].revents) {
 			i=read(err_pipe[0],buf,sizeof(buf)-1);
 			if(i!=-1 && i!=0) {
 				buf[i]=0;
@@ -4843,7 +4843,7 @@ static BOOL exec_cgi(http_session_t *session)
 			}
 		}
 
-		if(cd.fds[0].revents & POLLIN)  {
+		if(cd.fds[0].revents)  {
 			i=read(cd.fds[0].fd, buf, sizeof(buf));
 			if(i!=-1 && i!=0)  {
 				int snt=0;
diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp
index 909fb8dad3..1e61ae7fdc 100644
--- a/src/sbbs3/xtrn.cpp
+++ b/src/sbbs3/xtrn.cpp
@@ -1692,7 +1692,6 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 		if(!(mode&EX_NOLOG)) {
 			fds[1].fd = err_pipe[0];
 			fds[1].events = POLLIN;
-			fds[1].revents = 0;
 		}
 		while(!terminated) {
 			if(waitpid(pid, &i, WNOHANG)!=0)	/* child exited */
@@ -1717,7 +1716,7 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 			if(mode&EX_NOLOG)
 				poll(fds, 1, 1);
 			else {
-				while (poll(fds, 2, 1) > 0 && (fds[1].revents & POLLIN)
+				while (poll(fds, 2, 1) > 0 && (fds[1].revents)
 				    && (i < (int)sizeof(buf) - 1))  {
 					if((rd=read(err_pipe[0],bp,1))>0)  {
 						i+=rd;
@@ -1744,7 +1743,7 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 				}
 			}
 
-			data_waiting=fds[0].revents & POLLIN;
+			data_waiting=fds[0].revents;
 			if(i==0 && data_waiting==0)
 				continue;
 
diff --git a/src/xpdev/multisock.c b/src/xpdev/multisock.c
index 4c8493a560..984ecaa26c 100644
--- a/src/xpdev/multisock.c
+++ b/src/xpdev/multisock.c
@@ -364,7 +364,7 @@ SOCKET xpms_accept(struct xpms_set *xpms_set, union xp_sockaddr * addr,
 			for(i=0; i<xpms_set->sock_count; i++) {
 				if(xpms_set->socks[i].sock == INVALID_SOCKET)
 					continue;
-				if (fds[scnt].revents & (POLLERR | POLLNVAL)) {
+				if (fds[scnt].revents & ~(POLLIN)) {
 					scnt++;
 					closesocket(xpms_set->socks[i].sock);
 					xpms_set->lprintf(LOG_ERR, "%04d * Listening socket went bad", xpms_set->socks[i].sock);
diff --git a/src/xpdev/sockwrap.c b/src/xpdev/sockwrap.c
index b9c5eb5b40..c6f32f0377 100644
--- a/src/xpdev/sockwrap.c
+++ b/src/xpdev/sockwrap.c
@@ -305,7 +305,7 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout)
 		if (pfd.revents & (POLLERR | POLLNVAL))
 			return FALSE;
 
-		if(pfd.revents & (POLLIN | POLLHUP) && (rd_p !=NULL || wr_p==NULL))  {
+		if(pfd.revents & ~(POLLOUT) && (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)
@@ -483,7 +483,7 @@ BOOL socket_recvdone(SOCKET sock, int timeout)
 
 	switch (poll(&pfd, 1, timeout)) {
 		case 1:
-			if (pfd.revents & (POLLIN | POLLHUP)) {
+			if (pfd.revents) {
 				rd = recv(sock,&ch,1,MSG_PEEK);
 				if (rd == 1 || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE))
 					return FALSE;
-- 
GitLab