diff --git a/src/os/unix/ngx_darwin_sendfile_chain.c b/src/os/unix/ngx_darwin_sendfile_chain.c index 3caad0790..43f191326 100644 --- a/src/os/unix/ngx_darwin_sendfile_chain.c +++ b/src/os/unix/ngx_darwin_sendfile_chain.c @@ -33,6 +33,7 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) int rc; off_t send, prev_send, sent; off_t file_size; + ssize_t n; ngx_uint_t eintr; ngx_err_t err; ngx_buf_t *file; @@ -172,33 +173,13 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) rc, file->file_pos, sent, file_size + header.size); } else { - rc = writev(c->fd, header.iovs, header.count); + n = ngx_writev(c, &header); - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "writev: %d of %uz", rc, header.size); - - if (rc == -1) { - err = ngx_errno; - - switch (err) { - case NGX_EAGAIN: - break; - - case NGX_EINTR: - eintr = 1; - break; - - default: - wev->error = 1; - ngx_connection_error(c, err, "writev() failed"); - return NGX_CHAIN_ERROR; - } - - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, - "writev() not ready"); + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; } - sent = rc > 0 ? rc : 0; + sent = (n == NGX_AGAIN) ? 0 : n; } c->sent += sent; diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c index 76f6ef235..7199c8654 100644 --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -35,6 +35,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) int rc, flags; off_t send, prev_send, sent; size_t file_size; + ssize_t n; ngx_uint_t eintr, eagain; ngx_err_t err; ngx_buf_t *file; @@ -217,33 +218,13 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) rc, file->file_pos, sent, file_size + header.size); } else { - rc = writev(c->fd, header.iovs, header.count); + n = ngx_writev(c, &header); - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "writev: %d of %uz", rc, header.size); - - if (rc == -1) { - err = ngx_errno; - - switch (err) { - case NGX_EAGAIN: - break; - - case NGX_EINTR: - eintr = 1; - break; - - default: - wev->error = 1; - ngx_connection_error(c, err, "writev() failed"); - return NGX_CHAIN_ERROR; - } - - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, - "writev() not ready"); + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; } - sent = rc > 0 ? rc : 0; + sent = (n == NGX_AGAIN) ? 0 : n; } c->sent += sent; diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c index c83677f0f..f1fcc748a 100644 --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -33,6 +33,7 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) int rc, tcp_nodelay; off_t send, prev_send, sent; size_t file_size; + ssize_t n; ngx_err_t err; ngx_buf_t *file; ngx_uint_t eintr; @@ -199,32 +200,13 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) rc, file->file_pos, sent, file_size); } else { - rc = writev(c->fd, header.iovs, header.count); + n = ngx_writev(c, &header); - if (rc == -1) { - err = ngx_errno; - - switch (err) { - case NGX_EAGAIN: - break; - - case NGX_EINTR: - eintr = 1; - break; - - default: - wev->error = 1; - ngx_connection_error(c, err, "writev() failed"); - return NGX_CHAIN_ERROR; - } - - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, - "writev() not ready"); + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; } - sent = rc > 0 ? rc : 0; - - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O", sent); + sent = (n == NGX_AGAIN) ? 0 : n; } c->sent += sent; diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h index fa6a6a6ce..09f79175e 100644 --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -75,6 +75,9 @@ ngx_chain_t *ngx_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, size_t limit, ngx_log_t *log); +ssize_t ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec); + + extern ngx_os_io_t ngx_os_io; extern ngx_int_t ngx_ncpu; extern ngx_int_t ngx_max_sockets; diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c index d9c94dd69..e38a3aae0 100644 --- a/src/os/unix/ngx_writev_chain.c +++ b/src/os/unix/ngx_writev_chain.c @@ -15,8 +15,6 @@ ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { ssize_t n, sent; off_t send, prev_send; - ngx_uint_t eintr; - ngx_err_t err; ngx_chain_t *cl; ngx_event_t *wev; ngx_iovec_t vec; @@ -51,7 +49,6 @@ ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) vec.nalloc = NGX_IOVS_PREALLOCATE; for ( ;; ) { - eintr = 0; prev_send = send; /* create the iovec and coalesce the neighbouring bufs */ @@ -83,42 +80,18 @@ ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) send += vec.size; - n = writev(c->fd, vec.iovs, vec.count); + n = ngx_writev(c, &vec); - if (n == -1) { - err = ngx_errno; - - switch (err) { - case NGX_EAGAIN: - break; - - case NGX_EINTR: - eintr = 1; - break; - - default: - wev->error = 1; - (void) ngx_connection_error(c, err, "writev() failed"); - return NGX_CHAIN_ERROR; - } - - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, - "writev() not ready"); + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; } - sent = n > 0 ? n : 0; - - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent); + sent = (n == NGX_AGAIN) ? 0 : n; c->sent += sent; in = ngx_chain_update_sent(in, sent); - if (eintr) { - send = prev_send; - continue; - } - if (send - prev_send != sent) { wev->ready = 0; return in; @@ -203,3 +176,41 @@ ngx_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, size_t limit, return in; } + + +ssize_t +ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec) +{ + ssize_t n; + ngx_err_t err; + +eintr: + + n = writev(c->fd, vec->iovs, vec->count); + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "writev: %z of %uz", n, vec->size); + + if (n == -1) { + err = ngx_errno; + + switch (err) { + case NGX_EAGAIN: + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "writev() not ready"); + return NGX_AGAIN; + + case NGX_EINTR: + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "writev() was interrupted"); + goto eintr; + + default: + c->write->error = 1; + ngx_connection_error(c, err, "writev() failed"); + return NGX_ERROR; + } + } + + return n; +}