aboutsummaryrefslogtreecommitdiff
path: root/src/os/unix
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/unix')
-rw-r--r--src/os/unix/ngx_readv_chain.c36
-rw-r--r--src/os/unix/ngx_recv.c36
-rw-r--r--src/os/unix/ngx_socket.h7
3 files changed, 77 insertions, 2 deletions
diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c
index 454cfdcad..a3577ce19 100644
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -60,7 +60,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
"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 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
#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 c85fd453c..ddfae4dbe 100644
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -57,7 +57,7 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
"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 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
#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 fcc515335..ec66a6f83 100644
--- a/src/os/unix/ngx_socket.h
+++ b/src/os/unix/ngx_socket.h
@@ -38,6 +38,13 @@ int ngx_blocking(ngx_socket_t s);
#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);