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;
}