diff options
Diffstat (limited to 'src/os')
-rw-r--r-- | src/os/unix/ngx_freebsd_sendfile_chain.c | 11 | ||||
-rw-r--r-- | src/os/unix/ngx_readv_chain.c | 25 | ||||
-rw-r--r-- | src/os/unix/ngx_recv.c | 33 |
3 files changed, 51 insertions, 18 deletions
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c index b43562546..c24149928 100644 --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -25,8 +25,8 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) { int rc, eintr, eagain; char *prev; - ssize_t hsize, fsize, size; off_t sent, fprev; + ssize_t hsize, fsize, size; struct iovec *iov; struct sf_hdtr hdtr; ngx_err_t err; @@ -67,15 +67,14 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) if (prev == cl->hunk->pos) { iov->iov_len += cl->hunk->last - cl->hunk->pos; - prev = cl->hunk->last; } else { ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); iov->iov_base = cl->hunk->pos; iov->iov_len = cl->hunk->last - cl->hunk->pos; - prev = cl->hunk->last; } + prev = cl->hunk->last; hsize += cl->hunk->last - cl->hunk->pos; } @@ -118,14 +117,14 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) if (prev == cl->hunk->pos) { iov->iov_len += cl->hunk->last - cl->hunk->pos; - prev = cl->hunk->last; } else { ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR); iov->iov_base = cl->hunk->pos; iov->iov_len = cl->hunk->last - cl->hunk->pos; - prev = cl->hunk->last; } + + prev = cl->hunk->last; } /* @@ -182,6 +181,7 @@ ngx_log_debug(c->log, "NOPUSH"); "sendfile() sent only %qd bytes", sent); } else { + c->write->error = 1; ngx_log_error(NGX_LOG_CRIT, c->log, err, "sendfile() failed"); return NGX_CHAIN_ERROR; @@ -206,6 +206,7 @@ ngx_log_debug(c->log, "NOPUSH"); ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR"); } else { + c->write->error = 1; ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed"); return NGX_CHAIN_ERROR; } diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c index c83b076ce..f19569879 100644 --- a/src/os/unix/ngx_readv_chain.c +++ b/src/os/unix/ngx_readv_chain.c @@ -6,23 +6,30 @@ ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain) { + char *prev; ssize_t n; struct iovec *iov; ngx_err_t err; ngx_array_t io; -#if (NGX_SUPPRESS_WARN) + prev = NULL; iov = NULL; -#endif ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_ERROR); - /* TODO: coalesce the neighbouring chain entries */ + /* coalesce the neighbouring hunks */ while (chain) { - ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR); - iov->iov_base = chain->hunk->last; - iov->iov_len = chain->hunk->end - chain->hunk->last; + if (prev == chain->hunk->last) { + iov->iov_len += chain->hunk->end - chain->hunk->last; + + } else { + ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR); + iov->iov_base = chain->hunk->last; + iov->iov_len = chain->hunk->end - chain->hunk->last; + } + + prev = chain->hunk->end; chain = chain->next; } @@ -30,8 +37,12 @@ ngx_log_debug(c->log, "recv: %d:%d" _ io.nelts _ iov->iov_len); n = readv(c->fd, (struct iovec *) io.elts, io.nelts); - if (n == -1) { + if (n == 0) { + c->read->eof = 1; + + } else if (n == -1) { c->read->ready = 0; + c->read->error = 1; err = ngx_errno; if (err == NGX_EAGAIN) { diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c index e61cc333f..1a14fd963 100644 --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -18,15 +18,19 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { ngx_log_debug(c->log, "recv: eof:%d, avail:%d, err:%d" _ - rev->eof _ rev->available _ rev->error); + rev->kq_eof _ rev->available _ rev->kq_errno); if (rev->available == 0) { - if (rev->eof) { + if (rev->kq_eof) { rev->ready = 0; - if (rev->error) { - ngx_set_socket_errno(rev->error); - return ngx_unix_recv_error(rev, rev->error); + rev->eof = 1; + + if (rev->kq_errno) { + rev->error = 1; + ngx_set_socket_errno(rev->kq_errno); + return ngx_unix_recv_error(rev, rev->kq_errno); } + return 0; } else { @@ -43,8 +47,14 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) if (n >= 0) { if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { rev->available -= n; + + /* + * rev->available can be negative here because some additional + * bytes can be received between kevent() and recv() + */ + if (rev->available <= 0) { - if (!rev->eof) { + if (!rev->kq_eof) { rev->ready = 0; } @@ -60,10 +70,15 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) rev->ready = 0; } + if (n == 0) { + rev->eof = 1; + } + return n; } rev->ready = 0; + rev->error = 1; n = ngx_unix_recv_error(rev, ngx_socket_errno); } while (n == NGX_EINTR); @@ -89,10 +104,16 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) if ((size_t) n < size) { rev->ready = 0; } + + if (n == 0) { + rev->eof = 1; + } + return n; } rev->ready = 0; + rev->error = 1; n = ngx_unix_recv_error(rev, ngx_socket_errno); } while (n == NGX_EINTR); |