6824e9
diff -up stunnel-4.56/src/client.c.pollhup stunnel-4.56/src/client.c
6824e9
--- stunnel-4.56/src/client.c.pollhup	2016-03-31 17:17:01.438314029 +0200
6824e9
+++ stunnel-4.56/src/client.c	2016-03-31 17:25:48.573618470 +0200
6824e9
@@ -595,35 +595,6 @@ static void transfer(CLI *c) {
6824e9
             }
6824e9
         }
6824e9
 
6824e9
-        /****************************** check for hangup conditions */
6824e9
-        if(s_poll_hup(c->fds, c->sock_rfd->fd)) {
6824e9
-            s_log(LOG_INFO, "Read socket closed (hangup)");
6824e9
-            sock_open_rd=0;
6824e9
-        }
6824e9
-        if(s_poll_hup(c->fds, c->sock_wfd->fd)) {
6824e9
-            if(c->ssl_ptr) {
6824e9
-                s_log(LOG_ERR,
6824e9
-                    "Write socket closed (hangup) with %d unsent byte(s)",
6824e9
-                    c->ssl_ptr);
6824e9
-                longjmp(c->err, 1); /* reset the socket */
6824e9
-            }
6824e9
-            s_log(LOG_INFO, "Write socket closed (hangup)");
6824e9
-            sock_open_wr=0;
6824e9
-        }
6824e9
-        if(s_poll_hup(c->fds, c->ssl_rfd->fd) ||
6824e9
-                s_poll_hup(c->fds, c->ssl_wfd->fd)) {
6824e9
-            /* hangup -> buggy (e.g. Microsoft) peer:
6824e9
-             * SSL socket closed without close_notify alert */
6824e9
-            if(c->sock_ptr) {
6824e9
-                s_log(LOG_ERR,
6824e9
-                    "SSL socket closed (hangup) with %d unsent byte(s)",
6824e9
-                    c->sock_ptr);
6824e9
-                longjmp(c->err, 1); /* reset the socket */
6824e9
-            }
6824e9
-            s_log(LOG_INFO, "SSL socket closed (hangup)");
6824e9
-            SSL_set_shutdown(c->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
6824e9
-        }
6824e9
-
6824e9
         /****************************** retrieve results from c->fds */
6824e9
         sock_can_rd=s_poll_canread(c->fds, c->sock_rfd->fd);
6824e9
         sock_can_wr=s_poll_canwrite(c->fds, c->sock_wfd->fd);
6824e9
@@ -828,6 +799,36 @@ static void transfer(CLI *c) {
6824e9
             }
6824e9
         }
6824e9
 
6824e9
+        /****************************** check for hangup conditions */
6824e9
+        if(s_poll_rdhup(c->fds, c->sock_rfd->fd) &&
6824e9
+                    !s_poll_canread(c->fds, c->sock_rfd->fd)) {
6824e9
+            s_log(LOG_INFO, "Read socket closed (hangup)");
6824e9
+            sock_open_rd=0;
6824e9
+        }
6824e9
+        if(s_poll_hup(c->fds, c->sock_wfd->fd)) {
6824e9
+            if(c->ssl_ptr) {
6824e9
+                s_log(LOG_ERR,
6824e9
+                    "Write socket closed (hangup) with %d unsent byte(s)",
6824e9
+                    c->ssl_ptr);
6824e9
+                longjmp(c->err, 1); /* reset the socket */
6824e9
+            }
6824e9
+            s_log(LOG_INFO, "Write socket closed (hangup)");
6824e9
+            sock_open_wr=0;
6824e9
+        }
6824e9
+        if((s_poll_hup(c->fds, c->ssl_rfd->fd) && !s_poll_canread(c->fds, c->sock_rfd->fd)) ||
6824e9
+                s_poll_hup(c->fds, c->ssl_wfd->fd)) {
6824e9
+            /* hangup -> buggy (e.g. Microsoft) peer:
6824e9
+             * SSL socket closed without close_notify alert */
6824e9
+            if(c->sock_ptr) {
6824e9
+                s_log(LOG_ERR,
6824e9
+                    "SSL socket closed (hangup) with %d unsent byte(s)",
6824e9
+                    c->sock_ptr);
6824e9
+                longjmp(c->err, 1); /* reset the socket */
6824e9
+            }
6824e9
+            s_log(LOG_INFO, "SSL socket closed (hangup)");
6824e9
+            SSL_set_shutdown(c->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
6824e9
+        }
6824e9
+
6824e9
         /****************************** check write shutdown conditions */
6824e9
         if(sock_open_wr && SSL_get_shutdown(c->ssl)&SSL_RECEIVED_SHUTDOWN && !c->ssl_ptr) {
6824e9
             sock_open_wr=0; /* no further write allowed */
6824e9
diff -up stunnel-4.56/src/network.c.pollhup stunnel-4.56/src/network.c
6824e9
--- stunnel-4.56/src/network.c.pollhup	2013-03-13 14:41:02.000000000 +0100
6824e9
+++ stunnel-4.56/src/network.c	2016-03-31 17:25:48.574618494 +0200
6824e9
@@ -79,8 +79,12 @@ void s_poll_add(s_poll_set *fds, int fd,
6824e9
         fds->ufds[i].events=0;
6824e9
         fds->nfds++;
6824e9
     }
6824e9
-    if(rd)
6824e9
+    if(rd) {
6824e9
         fds->ufds[i].events|=POLLIN;
6824e9
+#ifdef POLLRDHUP
6824e9
+        fds->ufds[i].events|=POLLRDHUP;
6824e9
+#endif
6824e9
+    }
6824e9
     if(wr)
6824e9
         fds->ufds[i].events|=POLLOUT;
6824e9
 }
6824e9
@@ -103,12 +107,27 @@ int s_poll_canwrite(s_poll_set *fds, int
6824e9
     return 0; /* not listed in fds */
6824e9
 }
6824e9
 
6824e9
+/* best doc: http://lxr.free-electrons.com/source/net/ipv4/tcp.c#L456 */
6824e9
+
6824e9
 int s_poll_hup(s_poll_set *fds, int fd) {
6824e9
     unsigned int i;
6824e9
 
6824e9
     for(i=0; i<fds->nfds; i++)
6824e9
         if(fds->ufds[i].fd==fd)
6824e9
-            return fds->ufds[i].revents&POLLHUP;
6824e9
+            return fds->ufds[i].revents&POLLHUP; /* read and write closed */
6824e9
+    return 0; /* not listed in fds */
6824e9
+}
6824e9
+
6824e9
+int s_poll_rdhup(s_poll_set *fds, int fd) {
6824e9
+    unsigned int i;
6824e9
+
6824e9
+    for(i=0; i<fds->nfds; i++)
6824e9
+        if(fds->ufds[i].fd==fd)
6824e9
+#ifdef POLLRDHUP
6824e9
+            return fds->ufds[i].revents&POLLRDHUP; /* read closed */
6824e9
+#else
6824e9
+            return fds->ufds[i].revents&POLLHUP; /* read and write closed */
6824e9
+#endif
6824e9
     return 0; /* not listed in fds */
6824e9
 }
6824e9
 
6824e9
@@ -336,6 +355,12 @@ int s_poll_hup(s_poll_set *fds, int fd)
6824e9
     return 0; /* FIXME: how to detect HUP condition with select()? */
6824e9
 }
6824e9
 
6824e9
+int s_poll_rdhup(s_poll_set *fds, int fd) {
6824e9
+    (void)fds; /* skip warning about unused parameter */
6824e9
+    (void)fd; /* skip warning about unused parameter */
6824e9
+    return 0; /* FIXME: how to detect RDHUP condition with select()? */
6824e9
+}
6824e9
+
6824e9
 int s_poll_error(s_poll_set *fds, int fd) {
6824e9
     /* error conditions are signaled as read, but apparently *not* in Winsock:
6824e9
      * http://msdn.microsoft.com/en-us/library/windows/desktop/ms737625%28v=vs.85%29.aspx */
6824e9
diff -up stunnel-4.56/src/prototypes.h.pollhup stunnel-4.56/src/prototypes.h
6824e9
--- stunnel-4.56/src/prototypes.h.pollhup	2013-03-19 18:30:55.000000000 +0100
6824e9
+++ stunnel-4.56/src/prototypes.h	2016-03-31 17:25:48.574618494 +0200
6824e9
@@ -385,6 +385,7 @@ void s_poll_add(s_poll_set *, int, int,
6824e9
 int s_poll_canread(s_poll_set *, int);
6824e9
 int s_poll_canwrite(s_poll_set *, int);
6824e9
 int s_poll_hup(s_poll_set *, int);
6824e9
+int s_poll_rdhup(s_poll_set *, int);
6824e9
 int s_poll_error(s_poll_set *, int);
6824e9
 int s_poll_wait(s_poll_set *, int, int);
6824e9