From 90ca5a36c511c9753878408984efa31dd99e9dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net> Date: Sat, 10 Apr 2021 16:01:50 -0400 Subject: [PATCH] Finally document socket_check() behaviour. Tweak the poll() implementation to match. Should fix #248 --- src/xpdev/sockwrap.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/xpdev/sockwrap.c b/src/xpdev/sockwrap.c index c6f32f0377..78918c7ccd 100644 --- a/src/xpdev/sockwrap.c +++ b/src/xpdev/sockwrap.c @@ -270,6 +270,32 @@ off_t recvfilesocket(int sock, int file, off_t *offset, off_t count) /* Return true if connected, optionally sets *rd_p to true if read data available */ +/* + * The exact conditions where rd_p is set to TRUE and the return value + * is true or false are complex, but the intent appears to be as follows: + * + * If the remote has half-closed the socket, rd_p should be FALSE and + * the function should return FALSE. + * + * If we have half-closed the socket, wr_p should be TRUE and the function + * should return TRUE. + * + * If the socket is completely closed, wr_p should be TRUE, rd_p should be + * FALSE, and the function should return FALSE, unless rd_p is NULL in which + * case, the function should return TRUE. + * + * When the function is open in both directions, wr_p will indicate write + * buffers are available, rd_p will indicate data is available to be recv()ed + * and the return value should be TRUE. + * + * If the socket is invalid, rd_p should be FALSE, wr_p should be FALSE, and + * the function should return FALSE. + * + * These rules have various exceptions when errors are returned by select(), + * poll(), or recv(), which will generally cause a FALSE return with rd_p + * being FALSE and wr_p being FALSE if select/poll failed, or indicating + * available write buffers otherwise. + */ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout) { #ifdef PREFER_POLL @@ -297,12 +323,13 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout) return TRUE; if (j == 1) { - if (wr_p != NULL && (pfd.revents & POLLOUT)) + if (wr_p != NULL && (pfd.revents & POLLOUT)) { *wr_p = TRUE; - if (rd_p != NULL && (pfd.revents & POLLIN)) - *rd_p = TRUE; + if (rd_p == NULL) + return TRUE; + } - if (pfd.revents & (POLLERR | POLLNVAL)) + if (pfd.revents & (POLLERR | POLLNVAL | POLLHUP)) return FALSE; if(pfd.revents & ~(POLLOUT) && (rd_p !=NULL || wr_p==NULL)) { @@ -310,19 +337,18 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout) if(rd==1 || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE)) { if(rd_p!=NULL) *rd_p=TRUE; - return(TRUE); + return TRUE; } - return FALSE; } + return FALSE; } if (j == -1) { if (errno == EINTR || errno == ENOMEM) return TRUE; - return FALSE; } - return TRUE; + return FALSE; #else char ch; int i,rd; -- GitLab