[nginx] Refactored ngx_linux_sendfile_chain() even more.

Valentin Bartenev vbart at nginx.com
Tue Mar 3 13:12:13 UTC 2015


details:   http://hg.nginx.org/nginx/rev/c901f2764c27
branches:  
changeset: 5997:c901f2764c27
user:      Valentin Bartenev <vbart at nginx.com>
date:      Fri Feb 27 19:19:08 2015 +0300
description:
Refactored ngx_linux_sendfile_chain() even more.

The code that calls sendfile() was cut into a separate function.
This simplifies EINTR processing, yet is needed for the following
changes that add threads support.

diffstat:

 src/os/unix/ngx_linux_sendfile_chain.c |  106 ++++++++++++++++++--------------
 1 files changed, 60 insertions(+), 46 deletions(-)

diffs (155 lines):

diff -r ab660d7c9980 -r c901f2764c27 src/os/unix/ngx_linux_sendfile_chain.c
--- a/src/os/unix/ngx_linux_sendfile_chain.c	Tue Mar 03 01:15:21 2015 +0300
+++ b/src/os/unix/ngx_linux_sendfile_chain.c	Fri Feb 27 19:19:08 2015 +0300
@@ -10,6 +10,10 @@
 #include <ngx_event.h>
 
 
+static ssize_t ngx_linux_sendfile(ngx_connection_t *c, ngx_buf_t *file,
+    size_t size);
+
+
 /*
  * On Linux up to 2.4.21 sendfile() (syscall #187) works with 32-bit
  * offsets only, and the including <sys/sendfile.h> breaks the compiling,
@@ -36,16 +40,10 @@ ngx_linux_sendfile_chain(ngx_connection_
     ssize_t        n;
     ngx_err_t      err;
     ngx_buf_t     *file;
-    ngx_uint_t     eintr;
     ngx_event_t   *wev;
     ngx_chain_t   *cl;
     ngx_iovec_t    header;
     struct iovec   headers[NGX_IOVS_PREALLOCATE];
-#if (NGX_HAVE_SENDFILE64)
-    off_t          offset;
-#else
-    int32_t        offset;
-#endif
 
     wev = c->write;
 
@@ -67,7 +65,6 @@ ngx_linux_sendfile_chain(ngx_connection_
     header.nalloc = NGX_IOVS_PREALLOCATE;
 
     for ( ;; ) {
-        eintr = 0;
         prev_send = send;
 
         /* create the iovec and coalesce the neighbouring bufs */
@@ -161,43 +158,13 @@ ngx_linux_sendfile_chain(ngx_connection_
                 return NGX_CHAIN_ERROR;
             }
 #endif
-#if (NGX_HAVE_SENDFILE64)
-            offset = file->file_pos;
-#else
-            offset = (int32_t) file->file_pos;
-#endif
+            n = ngx_linux_sendfile(c, file, file_size);
 
-            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                           "sendfile: @%O %uz", file->file_pos, file_size);
-
-            n = sendfile(c->fd, file->file->fd, &offset, file_size);
-
-            if (n == -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, "sendfile() failed");
-                    return NGX_CHAIN_ERROR;
-                }
-
-                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
-                               "sendfile() is not ready");
+            if (n == NGX_ERROR) {
+                return NGX_CHAIN_ERROR;
             }
 
-            sent = n > 0 ? n : 0;
-
-            ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                           "sendfile: %z, @%O %O:%uz",
-                           n, file->file_pos, sent, file_size);
+            sent = (n == NGX_AGAIN) ? 0 : n;
 
         } else {
             n = ngx_writev(c, &header);
@@ -213,11 +180,6 @@ ngx_linux_sendfile_chain(ngx_connection_
 
         in = ngx_chain_update_sent(in, sent);
 
-        if (eintr) {
-            send = prev_send;
-            continue;
-        }
-
         if (send - prev_send != sent) {
             wev->ready = 0;
             return in;
@@ -228,3 +190,55 @@ ngx_linux_sendfile_chain(ngx_connection_
         }
     }
 }
+
+
+static ssize_t
+ngx_linux_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size)
+{
+#if (NGX_HAVE_SENDFILE64)
+    off_t      offset;
+#else
+    int32_t    offset;
+#endif
+    ssize_t    n;
+    ngx_err_t  err;
+
+#if (NGX_HAVE_SENDFILE64)
+    offset = file->file_pos;
+#else
+    offset = (int32_t) file->file_pos;
+#endif
+
+eintr:
+
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "sendfile: @%O %uz", file->file_pos, size);
+
+    n = sendfile(c->fd, file->file->fd, &offset, size);
+
+    if (n == -1) {
+        err = ngx_errno;
+
+        switch (err) {
+        case NGX_EAGAIN:
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                           "sendfile() is not ready");
+            return NGX_AGAIN;
+
+        case NGX_EINTR:
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                           "sendfile() was interrupted");
+            goto eintr;
+
+        default:
+            c->write->error = 1;
+            ngx_connection_error(c, err, "sendfile() failed");
+            return NGX_ERROR;
+        }
+    }
+
+    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: %z of %uz @%O",
+                   n, size, file->file_pos);
+
+    return n;
+}



More information about the nginx-devel mailing list