Merge branch 'nginx' (nginx-1.17.5). Change-Id: I275ecd6c5824a8397b6132da04c4154978552565 Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags index 19ec901..42f1877 100644 --- a/.hgtags +++ b/.hgtags
@@ -443,3 +443,4 @@ 2fc9f853a6b7cd29dc84e0af2ed3cf78e0da6ca8 release-1.17.2 ed4303aa1b31a9aad5440640c0840d9d0af45fed release-1.17.3 ce2ced3856909f36f8130c99eaa4dbdbae636ddc release-1.17.4 +9af0dddbddb2c368bfedd2801bc100ffad01e19b release-1.17.5
diff --git a/BUILD b/BUILD index bfe49ee..c2e5c91 100644 --- a/BUILD +++ b/BUILD
@@ -1520,5 +1520,5 @@ preinst = "@nginx_pkgoss//:debian_preinst", prerm = "@nginx_pkgoss//:debian_prerm", section = "httpd", - version = "1.17.4", + version = "1.17.5", )
diff --git a/auto/unix b/auto/unix index cdc5868..c3276f2 100644 --- a/auto/unix +++ b/auto/unix
@@ -943,6 +943,18 @@ . $NGX_AUTO/feature +ngx_feature="ioctl(FIONREAD)" +ngx_feature_name="NGX_HAVE_FIONREAD" +ngx_feature_run=no +ngx_feature_incs="#include <sys/ioctl.h> + #include <stdio.h> + $NGX_INCLUDE_SYS_FILIO_H" +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="int i = FIONREAD; printf(\"%d\", i)" +. $NGX_AUTO/feature + + ngx_feature="struct tm.tm_gmtoff" ngx_feature_name="NGX_HAVE_GMTOFF" ngx_feature_run=no
diff --git a/build.bzl b/build.bzl index 662cfa4..49060ce 100644 --- a/build.bzl +++ b/build.bzl
@@ -673,9 +673,9 @@ name = "nginx_pkgoss", build_file_content = _PKGOSS_BUILD_FILE.format(nginx = nginx) + _PKGOSS_BUILD_FILE_TAIL, - commit = "b111e7858767a7f112093e752eba1a27a69bf778", # nginx-1.17.4 + commit = "8358ebc96da490c997960f08b03ffff6d33ad2a5", # nginx-1.17.5 remote = "https://nginx.googlesource.com/nginx-pkgoss", - shallow_since = "1569336583 +0300", + shallow_since = "1571744169 +0300", ) def nginx_repositories_zlib(bind):
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index fd7e308..29738da 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,69 @@ <change_log title="nginx"> +<changes ver="1.17.5" date="2019-10-22"> + +<change type="feature"> +<para lang="ru"> +теперь nginx использует вызов ioctl(FIONREAD), если он доступен, +чтобы избежать чтения из быстрого соединения в течение долгого времени. +</para> +<para lang="en"> +now nginx uses ioctl(FIONREAD), if available, +to avoid reading from a fast connection for a long time. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +неполные закодированные символы в конце URI запроса игнорировались. +</para> +<para lang="en"> +incomplete escaped characters at the end of the request URI were ignored. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +"/." и "/.." в конце URI запроса не нормализовывались. +</para> +<para lang="en"> +"/." and "/.." at the end of the request URI were not normalized. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +в директиве merge_slashes. +</para> +<para lang="en"> +in the "merge_slashes" directive. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +в директиве ignore_invalid_headers.<br/> +Спасибо Alan Kemp. +</para> +<para lang="en"> +in the "ignore_invalid_headers" directive.<br/> +Thanks to Alan Kemp. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +nginx не собирался с MinGW-w64 gcc 8.1 и новее. +</para> +<para lang="en"> +nginx could not be built with MinGW-w64 gcc 8.1 or newer. +</para> +</change> + +</changes> + + <changes ver="1.17.4" date="2019-09-24"> <change type="change">
diff --git a/src/core/nginx.h b/src/core/nginx.h index 053201d..6910a87 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h
@@ -13,8 +13,8 @@ #define NGINX_NAME "nginx" #endif -#define nginx_version 1017004 -#define NGINX_VERSION "1.17.4" +#define nginx_version 1017005 +#define NGINX_VERSION "1.17.5" #define NGINX_VER NGINX_NAME "/" NGINX_VERSION #ifdef NGX_BUILD
diff --git a/src/core/ngx_rbtree.c b/src/core/ngx_rbtree.c index 969d549..377b82f 100644 --- a/src/core/ngx_rbtree.c +++ b/src/core/ngx_rbtree.c
@@ -174,12 +174,7 @@ } else { subst = ngx_rbtree_min(node->right, sentinel); - - if (subst->left != sentinel) { - temp = subst->left; - } else { - temp = subst->right; - } + temp = subst->right; } if (subst == *root) {
diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c index b7bf98d..d955754 100644 --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c
@@ -497,6 +497,7 @@ if ((revents & POLLIN) && rev->active) { rev->ready = 1; + rev->available = -1; if (flags & NGX_POST_EVENTS) { queue = rev->accept ? &ngx_posted_accept_events
diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c index 09e5e48..fa79d07 100644 --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c
@@ -894,11 +894,10 @@ if (revents & EPOLLRDHUP) { rev->pending_eof = 1; } - - rev->available = 1; #endif rev->ready = 1; + rev->available = -1; if (flags & NGX_POST_EVENTS) { queue = rev->accept ? &ngx_posted_accept_events
diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c index 061c996..ffc98e1 100644 --- a/src/event/modules/ngx_eventport_module.c +++ b/src/event/modules/ngx_eventport_module.c
@@ -571,6 +571,7 @@ if (revents & POLLIN) { rev->ready = 1; + rev->available = -1; if (flags & NGX_POST_EVENTS) { queue = rev->accept ? &ngx_posted_accept_events
diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c index a12c112..9259030 100644 --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c
@@ -372,6 +372,7 @@ ev = c->read; ev->ready = 1; + ev->available = -1; queue = ev->accept ? &ngx_posted_accept_events : &ngx_posted_events;
diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c index 59810f6..9d84d79 100644 --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c
@@ -332,6 +332,7 @@ if (found) { ev->ready = 1; + ev->available = -1; queue = ev->accept ? &ngx_posted_accept_events : &ngx_posted_events;
diff --git a/src/event/modules/ngx_win32_poll_module.c b/src/event/modules/ngx_win32_poll_module.c index 9fe867f..2fbc1b3 100644 --- a/src/event/modules/ngx_win32_poll_module.c +++ b/src/event/modules/ngx_win32_poll_module.c
@@ -380,6 +380,7 @@ ev = c->read; ev->ready = 1; + ev->available = -1; queue = ev->accept ? &ngx_posted_accept_events : &ngx_posted_events;
diff --git a/src/event/modules/ngx_win32_select_module.c b/src/event/modules/ngx_win32_select_module.c index c464805..c6e1bcf 100644 --- a/src/event/modules/ngx_win32_select_module.c +++ b/src/event/modules/ngx_win32_select_module.c
@@ -332,6 +332,7 @@ if (found) { ev->ready = 1; + ev->available = -1; queue = ev->accept ? &ngx_posted_accept_events : &ngx_posted_events;
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index 32c637d..f173945 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c
@@ -237,6 +237,12 @@ } } + if (!ngx_queue_empty(&ngx_posted_next_events)) { + ngx_queue_add(&ngx_posted_events, &ngx_posted_next_events); + ngx_queue_init(&ngx_posted_next_events); + timer = 0; + } + delta = ngx_current_msec; (void) ngx_process_events(cycle, timer, flags); @@ -639,6 +645,7 @@ #endif ngx_queue_init(&ngx_posted_accept_events); + ngx_queue_init(&ngx_posted_next_events); ngx_queue_init(&ngx_posted_events); if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index f6eaf8c..3b8e50c 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h
@@ -91,21 +91,14 @@ * write: available space in buffer when event is ready * or lowat when event is set with NGX_LOWAT_EVENT flag * - * epoll with EPOLLRDHUP: - * accept: 1 if accept many, 0 otherwise - * read: 1 if there can be data to read, 0 otherwise - * * iocp: TODO * * otherwise: * accept: 1 if accept many, 0 otherwise + * read: bytes to read when event is ready, -1 if not known */ -#if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP) int available; -#else - unsigned available:1; -#endif ngx_event_handler_pt handler;
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index b8d7b08..7d16b1f 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c
@@ -43,6 +43,7 @@ #endif static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n); static void ngx_ssl_write_handler(ngx_event_t *wev); +static void ngx_ssl_next_read_handler(ngx_event_t *rev); #ifdef SSL_READ_EARLY_DATA_SUCCESS static ssize_t ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size); @@ -1945,6 +1946,10 @@ last += n; bytes += n; + if (!c->read->ready) { + return bytes; + } + if (last == b->end) { cl = cl->next; @@ -2022,6 +2027,48 @@ if (size == 0) { c->read->ready = 1; + + if (c->read->available >= 0) { + c->read->available -= bytes; + + /* + * there can be data buffered at SSL layer, + * so we post an event to continue reading on the next + * iteration of the event loop + */ + + if (c->read->available < 0) { + c->read->available = 0; + c->read->ready = 0; + + if (c->ssl->next_read_handler == NULL) { + c->ssl->next_read_handler = c->read->handler; + c->read->handler = ngx_ssl_next_read_handler; + } + + ngx_post_event(c->read, &ngx_posted_next_events); + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL_read: avail:%d", c->read->available); + + } else { + +#if (NGX_HAVE_FIONREAD) + + if (ngx_socket_nread(c->fd, &c->read->available) == -1) { + c->read->error = 1; + ngx_connection_error(c, ngx_socket_errno, + ngx_socket_nread_n " failed"); + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL_read: avail:%d", c->read->available); + +#endif + } + return bytes; } @@ -2304,6 +2351,31 @@ } +static void +ngx_ssl_next_read_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + + c = rev->data; + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL next read handler"); + + rev->handler = c->ssl->next_read_handler; + c->ssl->next_read_handler = NULL; + + if (!rev->ready) { + rev->ready = 1; + rev->available = -1; + } + + if (rev->posted) { + ngx_delete_posted_event(rev); + } + + rev->handler(rev); +} + + /* * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer * before the SSL_write() call to decrease a SSL overhead.
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index f34ccf9..7aa471b 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h
@@ -86,6 +86,7 @@ ngx_event_handler_pt saved_read_handler; ngx_event_handler_pt saved_write_handler; + ngx_event_handler_pt next_read_handler; u_char early_buf;
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c index da7c4ee..531b13a 100644 --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c
@@ -172,7 +172,11 @@ */ if (p->upstream->read->available == 0 - && p->upstream->read->pending_eof) + && p->upstream->read->pending_eof +#if (NGX_SSL) + && !p->upstream->ssl +#endif + ) { p->upstream->read->ready = 0; p->upstream->read->eof = 1;
diff --git a/src/event/ngx_event_posted.c b/src/event/ngx_event_posted.c index d851f3d..fd0b411 100644 --- a/src/event/ngx_event_posted.c +++ b/src/event/ngx_event_posted.c
@@ -11,6 +11,7 @@ ngx_queue_t ngx_posted_accept_events; +ngx_queue_t ngx_posted_next_events; ngx_queue_t ngx_posted_events;
diff --git a/src/event/ngx_event_posted.h b/src/event/ngx_event_posted.h index 145d30f..bac5b35 100644 --- a/src/event/ngx_event_posted.h +++ b/src/event/ngx_event_posted.h
@@ -42,6 +42,7 @@ extern ngx_queue_t ngx_posted_accept_events; +extern ngx_queue_t ngx_posted_next_events; extern ngx_queue_t ngx_posted_events;
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index 8e1b118..cfc42f9 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c
@@ -912,6 +912,8 @@ i = 1; } else { + hash = 0; + i = 0; r->invalid_header = 1; } @@ -922,6 +924,8 @@ return NGX_HTTP_PARSE_INVALID_HEADER; } + hash = 0; + i = 0; r->invalid_header = 1; break; @@ -1437,9 +1441,11 @@ state = sw_quoted; break; case '?': + u--; r->args_start = p; goto args; case '#': + u--; goto done; case '+': r->plus_in_uri = 1; @@ -1467,8 +1473,9 @@ case '\\': #endif case '/': - state = sw_slash; - u -= 5; + case '?': + case '#': + u -= 4; for ( ;; ) { if (u < r->uri.data) { return NGX_HTTP_PARSE_INVALID_REQUEST; @@ -1479,16 +1486,19 @@ } u--; } + if (ch == '?') { + r->args_start = p; + goto args; + } + if (ch == '#') { + goto done; + } + state = sw_slash; break; case '%': quoted_state = state; state = sw_quoted; break; - case '?': - r->args_start = p; - goto args; - case '#': - goto done; case '+': r->plus_in_uri = 1; /* fall through */ @@ -1561,6 +1571,30 @@ } } + if (state == sw_quoted || state == sw_quoted_second) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + + if (state == sw_dot) { + u--; + + } else if (state == sw_dot_dot) { + u -= 4; + + for ( ;; ) { + if (u < r->uri.data) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + + if (*u == '/') { + u++; + break; + } + + u--; + } + } + done: r->uri.len = u - r->uri.data;
diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c index 454cfdc..a3577ce 100644 --- a/src/os/unix/ngx_readv_chain.c +++ b/src/os/unix/ngx_readv_chain.c
@@ -60,7 +60,7 @@ "readv: eof:%d, avail:%d", rev->pending_eof, rev->available); - if (!rev->available && !rev->pending_eof) { + if (rev->available == 0 && !rev->pending_eof) { return NGX_AGAIN; } } @@ -165,6 +165,40 @@ #endif +#if (NGX_HAVE_FIONREAD) + + if (rev->available >= 0) { + rev->available -= n; + + /* + * negative rev->available means some additional bytes + * were received between kernel notification and readv(), + * and therefore ev->ready can be safely reset even for + * edge-triggered event methods + */ + + if (rev->available < 0) { + rev->available = 0; + rev->ready = 0; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "readv: avail:%d", rev->available); + + } else if (n == size) { + + if (ngx_socket_nread(c->fd, &rev->available) == -1) { + n = ngx_connection_error(c, ngx_socket_errno, + ngx_socket_nread_n " failed"); + break; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "readv: avail:%d", rev->available); + } + +#endif + #if (NGX_HAVE_EPOLLRDHUP) if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c index c85fd45..ddfae4d 100644 --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c
@@ -57,7 +57,7 @@ "recv: eof:%d, avail:%d", rev->pending_eof, rev->available); - if (!rev->available && !rev->pending_eof) { + if (rev->available == 0 && !rev->pending_eof) { rev->ready = 0; return NGX_AGAIN; } @@ -116,6 +116,40 @@ #endif +#if (NGX_HAVE_FIONREAD) + + if (rev->available >= 0) { + rev->available -= n; + + /* + * negative rev->available means some additional bytes + * were received between kernel notification and recv(), + * and therefore ev->ready can be safely reset even for + * edge-triggered event methods + */ + + if (rev->available < 0) { + rev->available = 0; + rev->ready = 0; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "recv: avail:%d", rev->available); + + } else if ((size_t) n == size) { + + if (ngx_socket_nread(c->fd, &rev->available) == -1) { + n = ngx_connection_error(c, ngx_socket_errno, + ngx_socket_nread_n " failed"); + break; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "recv: avail:%d", rev->available); + } + +#endif + #if (NGX_HAVE_EPOLLRDHUP) if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
diff --git a/src/os/unix/ngx_socket.h b/src/os/unix/ngx_socket.h index fcc5153..ec66a6f 100644 --- a/src/os/unix/ngx_socket.h +++ b/src/os/unix/ngx_socket.h
@@ -38,6 +38,13 @@ #endif +#if (NGX_HAVE_FIONREAD) + +#define ngx_socket_nread(s, n) ioctl(s, FIONREAD, n) +#define ngx_socket_nread_n "ioctl(FIONREAD)" + +#endif + int ngx_tcp_nopush(ngx_socket_t s); int ngx_tcp_push(ngx_socket_t s);
diff --git a/src/os/win32/ngx_errno.c b/src/os/win32/ngx_errno.c index b732bf4..966d3de 100644 --- a/src/os/win32/ngx_errno.c +++ b/src/os/win32/ngx_errno.c
@@ -22,7 +22,7 @@ len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, lang, (char *) errstr, size, NULL); - if (len == 0 && lang && GetLastError() == ERROR_RESOURCE_LANG_NOT_FOUND) { + if (len == 0 && lang) { /* * Try to use English messages first and fallback to a language,
diff --git a/src/os/win32/ngx_socket.c b/src/os/win32/ngx_socket.c index 05a39f4..b1b4afb 100644 --- a/src/os/win32/ngx_socket.c +++ b/src/os/win32/ngx_socket.c
@@ -28,6 +28,21 @@ int +ngx_socket_nread(ngx_socket_t s, int *n) +{ + unsigned long nread; + + if (ioctlsocket(s, FIONREAD, &nread) == -1) { + return -1; + } + + *n = nread; + + return 0; +} + + +int ngx_tcp_push(ngx_socket_t s) { return 0;
diff --git a/src/os/win32/ngx_socket.h b/src/os/win32/ngx_socket.h index f8a453d..ab56bc8 100644 --- a/src/os/win32/ngx_socket.h +++ b/src/os/win32/ngx_socket.h
@@ -31,6 +31,9 @@ #define ngx_nonblocking_n "ioctlsocket(FIONBIO)" #define ngx_blocking_n "ioctlsocket(!FIONBIO)" +int ngx_socket_nread(ngx_socket_t s, int *n); +#define ngx_socket_nread_n "ioctlsocket(FIONREAD)" + #define ngx_shutdown_socket shutdown #define ngx_shutdown_socket_n "shutdown()"
diff --git a/src/os/win32/ngx_win32_config.h b/src/os/win32/ngx_win32_config.h index 4824d05..9615687 100644 --- a/src/os/win32/ngx_win32_config.h +++ b/src/os/win32/ngx_win32_config.h
@@ -273,6 +273,10 @@ #define NGX_HAVE_SO_SNDLOWAT 0 #endif +#ifndef NGX_HAVE_FIONREAD +#define NGX_HAVE_FIONREAD 1 +#endif + #define NGX_HAVE_GETADDRINFO 1 #define ngx_random rand
diff --git a/src/os/win32/ngx_win32_init.c b/src/os/win32/ngx_win32_init.c index 70bee8e..3249fb2 100644 --- a/src/os/win32/ngx_win32_init.c +++ b/src/os/win32/ngx_win32_init.c
@@ -240,7 +240,7 @@ goto nopoll; } - WSAPoll = (ngx_wsapoll_pt) GetProcAddress(hmod, "WSAPoll"); + WSAPoll = (ngx_wsapoll_pt) (void *) GetProcAddress(hmod, "WSAPoll"); if (WSAPoll == NULL) { ngx_log_error(NGX_LOG_NOTICE, log, ngx_errno, "GetProcAddress(\"WSAPoll\") failed");
diff --git a/src/os/win32/ngx_wsarecv.c b/src/os/win32/ngx_wsarecv.c index 1925f0b..ac88310 100644 --- a/src/os/win32/ngx_wsarecv.c +++ b/src/os/win32/ngx_wsarecv.c
@@ -51,6 +51,45 @@ return n; } +#if (NGX_HAVE_FIONREAD) + + if (rev->available >= 0 && bytes > 0) { + rev->available -= bytes; + + /* + * negative rev->available means some additional bytes + * were received between kernel notification and WSARecv(), + * and therefore ev->ready can be safely reset even for + * edge-triggered event methods + */ + + if (rev->available < 0) { + rev->available = 0; + rev->ready = 0; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "WSARecv: avail:%d", rev->available); + + } else if (bytes == size) { + + if (ngx_socket_nread(c->fd, &rev->available) == -1) { + n = ngx_connection_error(c, ngx_socket_errno, + ngx_socket_nread_n " failed"); + + if (n == NGX_ERROR) { + rev->error = 1; + } + + return n; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "WSARecv: avail:%d", rev->available); + } + +#endif + if (bytes < size) { rev->ready = 0; }
diff --git a/src/os/win32/ngx_wsarecv_chain.c b/src/os/win32/ngx_wsarecv_chain.c index 2598e09..87f0239 100644 --- a/src/os/win32/ngx_wsarecv_chain.c +++ b/src/os/win32/ngx_wsarecv_chain.c
@@ -94,6 +94,41 @@ return NGX_ERROR; } +#if (NGX_HAVE_FIONREAD) + + if (rev->available >= 0 && bytes > 0) { + rev->available -= bytes; + + /* + * negative rev->available means some additional bytes + * were received between kernel notification and WSARecv(), + * and therefore ev->ready can be safely reset even for + * edge-triggered event methods + */ + + if (rev->available < 0) { + rev->available = 0; + rev->ready = 0; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "WSARecv: avail:%d", rev->available); + + } else if (bytes == size) { + + if (ngx_socket_nread(c->fd, &rev->available) == -1) { + rev->error = 1; + ngx_connection_error(c, ngx_socket_errno, + ngx_socket_nread_n " failed"); + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "WSARecv: avail:%d", rev->available); + } + +#endif + if (bytes < size) { rev->ready = 0; }