ssl: close sometimes continuously asserting POLLIN until timeout
authorSilas Parker <skyhisi@user.github.invalid.com>
Thu, 9 Mar 2017 23:46:05 +0000 (07:46 +0800)
committerAndy Green <andy@warmcat.com>
Thu, 9 Mar 2017 23:46:05 +0000 (07:46 +0800)
https://github.com/warmcat/libwebsockets/issues/831

lib/libwebsockets.c
lib/service.c

index c98e60b..cc4d9e1 100755 (executable)
@@ -483,9 +483,10 @@ just_kill_connection:
                {
                        lwsl_info("%s: shutting down SSL connection: %p (ssl %p, sock %d, state %d)\n", __func__, wsi, wsi->ssl, (int)(long)wsi->desc.sockfd, wsi->state);
                        n = SSL_shutdown(wsi->ssl);
-                       if (n == 0) /* Complete bidirectional SSL shutdown */
-                               SSL_shutdown(wsi->ssl);
-                       n = shutdown(wsi->desc.sockfd, SHUT_WR);
+                       if (n == 1) /* If finished the SSL shutdown, then do socket shutdown, else need to retry SSL shutdown */
+                               n = shutdown(wsi->desc.sockfd, SHUT_WR);
+                       else
+                               lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
                }
                else
 #endif
index 4b15319..050a8ce 100644 (file)
@@ -839,10 +839,30 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
 
 #endif
 
-       lwsl_debug("fd=%d, revents=%d\n", pollfd->fd, pollfd->revents);
+       lwsl_debug("fd=%d, revents=%d, mode=%d, state=%d\n", pollfd->fd, pollfd->revents, (int)wsi->mode, (int)wsi->state);
        if (pollfd->revents & LWS_POLLHUP)
                goto close_and_handled;
 
+
+#ifdef LWS_OPENSSL_SUPPORT
+       if ((wsi->state == LWSS_SHUTDOWN) && lws_is_ssl(wsi) && wsi->ssl)
+       {
+               n = SSL_shutdown(wsi->ssl);
+               lwsl_debug("SSH_shutdown=%d for fd %d\n", n, wsi->desc.sockfd);
+               if (n == 1)
+               {
+                       n = shutdown(wsi->desc.sockfd, SHUT_WR);
+                       goto close_and_handled;
+               }
+               else
+               {
+                       lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
+                       n = 0;
+                       goto handled;
+               }
+       }
+#endif
+
        /* okay, what we came here to do... */
 
        switch (wsi->mode) {