Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 
0012 
0013 ssize_t
0014 ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
0015 {
0016     u_char        *prev;
0017     ssize_t        n, size;
0018     ngx_err_t      err;
0019     ngx_array_t    vec;
0020     ngx_event_t   *rev;
0021     struct iovec  *iov, iovs[NGX_IOVS_PREALLOCATE];
0022 
0023     rev = c->read;
0024 
0025 #if (NGX_HAVE_KQUEUE)
0026 
0027     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
0028         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
0029                        "readv: eof:%d, avail:%d, err:%d",
0030                        rev->pending_eof, rev->available, rev->kq_errno);
0031 
0032         if (rev->available == 0) {
0033             if (rev->pending_eof) {
0034                 rev->ready = 0;
0035                 rev->eof = 1;
0036 
0037                 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
0038                               "kevent() reported about an closed connection");
0039 
0040                 if (rev->kq_errno) {
0041                     rev->error = 1;
0042                     ngx_set_socket_errno(rev->kq_errno);
0043                     return NGX_ERROR;
0044                 }
0045 
0046                 return 0;
0047 
0048             } else {
0049                 return NGX_AGAIN;
0050             }
0051         }
0052     }
0053 
0054 #endif
0055 
0056 #if (NGX_HAVE_EPOLLRDHUP)
0057 
0058     if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
0059         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
0060                        "readv: eof:%d, avail:%d",
0061                        rev->pending_eof, rev->available);
0062 
0063         if (!rev->available && !rev->pending_eof) {
0064             return NGX_AGAIN;
0065         }
0066     }
0067 
0068 #endif
0069 
0070     prev = NULL;
0071     iov = NULL;
0072     size = 0;
0073 
0074     vec.elts = iovs;
0075     vec.nelts = 0;
0076     vec.size = sizeof(struct iovec);
0077     vec.nalloc = NGX_IOVS_PREALLOCATE;
0078     vec.pool = c->pool;
0079 
0080     /* coalesce the neighbouring bufs */
0081 
0082     while (chain) {
0083         n = chain->buf->end - chain->buf->last;
0084 
0085         if (limit) {
0086             if (size >= limit) {
0087                 break;
0088             }
0089 
0090             if (size + n > limit) {
0091                 n = (ssize_t) (limit - size);
0092             }
0093         }
0094 
0095         if (prev == chain->buf->last) {
0096             iov->iov_len += n;
0097 
0098         } else {
0099             if (vec.nelts >= IOV_MAX) {
0100                 break;
0101             }
0102 
0103             iov = ngx_array_push(&vec);
0104             if (iov == NULL) {
0105                 return NGX_ERROR;
0106             }
0107 
0108             iov->iov_base = (void *) chain->buf->last;
0109             iov->iov_len = n;
0110         }
0111 
0112         size += n;
0113         prev = chain->buf->end;
0114         chain = chain->next;
0115     }
0116 
0117     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
0118                    "readv: %ui, last:%uz", vec.nelts, iov->iov_len);
0119 
0120     do {
0121         n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
0122 
0123         if (n == 0) {
0124             rev->ready = 0;
0125             rev->eof = 1;
0126 
0127 #if (NGX_HAVE_KQUEUE)
0128 
0129             /*
0130              * on FreeBSD readv() may return 0 on closed socket
0131              * even if kqueue reported about available data
0132              */
0133 
0134             if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
0135                 rev->available = 0;
0136             }
0137 
0138 #endif
0139 
0140             return 0;
0141         }
0142 
0143         if (n > 0) {
0144 
0145 #if (NGX_HAVE_KQUEUE)
0146 
0147             if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
0148                 rev->available -= n;
0149 
0150                 /*
0151                  * rev->available may be negative here because some additional
0152                  * bytes may be received between kevent() and readv()
0153                  */
0154 
0155                 if (rev->available <= 0) {
0156                     if (!rev->pending_eof) {
0157                         rev->ready = 0;
0158                     }
0159 
0160                     rev->available = 0;
0161                 }
0162 
0163                 return n;
0164             }
0165 
0166 #endif
0167 
0168 #if (NGX_HAVE_EPOLLRDHUP)
0169 
0170             if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
0171                 && ngx_use_epoll_rdhup)
0172             {
0173                 if (n < size) {
0174                     if (!rev->pending_eof) {
0175                         rev->ready = 0;
0176                     }
0177 
0178                     rev->available = 0;
0179                 }
0180 
0181                 return n;
0182             }
0183 
0184 #endif
0185 
0186             if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) {
0187                 rev->ready = 0;
0188             }
0189 
0190             return n;
0191         }
0192 
0193         err = ngx_socket_errno;
0194 
0195         if (err == NGX_EAGAIN || err == NGX_EINTR) {
0196             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
0197                            "readv() not ready");
0198             n = NGX_AGAIN;
0199 
0200         } else {
0201             n = ngx_connection_error(c, err, "readv() failed");
0202             break;
0203         }
0204 
0205     } while (err == NGX_EINTR);
0206 
0207     rev->ready = 0;
0208 
0209     if (n == NGX_ERROR) {
0210         c->read->error = 1;
0211     }
0212 
0213     return n;
0214 }