diff --git a/mongoose.c b/mongoose.c index a5d1bcdb..f9108244 100644 --- a/mongoose.c +++ b/mongoose.c @@ -4366,7 +4366,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { eSELECT_READ | eSELECT_EXCEPT | eSELECT_WRITE); } #elif MG_ENABLE_POLL - size_t n = 0; + unsigned long n = 0; for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) n++; struct pollfd *fds = (struct pollfd *) alloca(n * sizeof(fds[0])); if (n > 0) memset(fds, 0, sizeof(n * sizeof(fds[0]))); @@ -4375,28 +4375,39 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { c->is_readable = c->is_writable = 0; if (skip_iotest(c)) { // Socket not valid, ignore + } else if (mg_tls_pending(c) > 0) { + ms = 1; // Don't wait if TLS is ready } else { fds[n].fd = FD(c); fds[n].events = POLLERR; if (can_read(c)) fds[n].events |= POLLIN; if (can_write(c)) fds[n].events |= POLLOUT; n++; - if (mg_tls_pending(c) > 0) ms = 0; // Don't wait if TLS is ready } } + // MG_INFO(("poll n=%d ms=%d", (int) n, ms)); if (poll(fds, n, ms) < 0) { - MG_ERROR(("poll failed, errno: %d", MG_SOCK_ERRNO)); - } else { - n = 0; - for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) { - if (skip_iotest(c)) continue; +#if MG_ARCH == MG_ARCH_WIN32 + if (n == 0) Sleep(ms); // On Windows, poll fails if no sockets +#endif + if (n > 0) memset(fds, 0, sizeof(n * sizeof(fds[0]))); + } + n = 0; + for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) { + if (skip_iotest(c)) { + // Socket not valid, ignore + } else if (mg_tls_pending(c) > 0) { + c->is_readable = 1; + } else { if (fds[n].revents & POLLERR) { mg_error(c, "socket error"); } else { - c->is_readable = (unsigned) (fds[n].revents & POLLIN ? 1 : 0); + c->is_readable = + (unsigned) (fds[n].revents & POLLIN || fds[n].revents & POLLHUP + ? 1 + : 0); c->is_writable = (unsigned) (fds[n].revents & POLLOUT ? 1 : 0); - if (mg_tls_pending(c) > 0) c->is_readable = 1; } n++; } diff --git a/src/sock.c b/src/sock.c index a210fa98..385e968b 100644 --- a/src/sock.c +++ b/src/sock.c @@ -518,7 +518,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { eSELECT_READ | eSELECT_EXCEPT | eSELECT_WRITE); } #elif MG_ENABLE_POLL - size_t n = 0; + unsigned long n = 0; for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) n++; struct pollfd *fds = (struct pollfd *) alloca(n * sizeof(fds[0])); if (n > 0) memset(fds, 0, sizeof(n * sizeof(fds[0]))); @@ -527,28 +527,39 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { c->is_readable = c->is_writable = 0; if (skip_iotest(c)) { // Socket not valid, ignore + } else if (mg_tls_pending(c) > 0) { + ms = 1; // Don't wait if TLS is ready } else { fds[n].fd = FD(c); fds[n].events = POLLERR; if (can_read(c)) fds[n].events |= POLLIN; if (can_write(c)) fds[n].events |= POLLOUT; n++; - if (mg_tls_pending(c) > 0) ms = 0; // Don't wait if TLS is ready } } + // MG_INFO(("poll n=%d ms=%d", (int) n, ms)); if (poll(fds, n, ms) < 0) { - MG_ERROR(("poll failed, errno: %d", MG_SOCK_ERRNO)); - } else { - n = 0; - for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) { - if (skip_iotest(c)) continue; +#if MG_ARCH == MG_ARCH_WIN32 + if (n == 0) Sleep(ms); // On Windows, poll fails if no sockets +#endif + if (n > 0) memset(fds, 0, sizeof(n * sizeof(fds[0]))); + } + n = 0; + for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) { + if (skip_iotest(c)) { + // Socket not valid, ignore + } else if (mg_tls_pending(c) > 0) { + c->is_readable = 1; + } else { if (fds[n].revents & POLLERR) { mg_error(c, "socket error"); } else { - c->is_readable = (unsigned) (fds[n].revents & POLLIN ? 1 : 0); + c->is_readable = + (unsigned) (fds[n].revents & POLLIN || fds[n].revents & POLLHUP + ? 1 + : 0); c->is_writable = (unsigned) (fds[n].revents & POLLOUT ? 1 : 0); - if (mg_tls_pending(c) > 0) c->is_readable = 1; } n++; } diff --git a/test/unit_test.c b/test/unit_test.c index 6f5c8cee..773853ba 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -1022,7 +1022,8 @@ static void test_http_no_content_length(void) { mg_mgr_init(&mgr); mg_http_listen(&mgr, url, f4, (void *) buf1); mg_http_connect(&mgr, url, f4c, (void *) buf2); - for (i = 0; i < 100 && strchr(buf2, 'c') == NULL; i++) mg_mgr_poll(&mgr, 1); + for (i = 0; i < 1000 && strchr(buf2, 'c') == NULL; i++) mg_mgr_poll(&mgr, 10); + MG_INFO(("[%s] [%s]", buf1, buf2)); ASSERT(strcmp(buf1, "mc") == 0); ASSERT(strcmp(buf2, "fcm") == 0); // See #1475 mg_mgr_free(&mgr);