| 11 | |
| 12 | |
| 13 | ngx_chain_t * |
| 14 | ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) |
| 15 | { |
| 16 | ssize_t n, sent; |
| 17 | off_t send, prev_send; |
| 18 | ngx_chain_t *cl; |
| 19 | ngx_event_t *wev; |
| 20 | ngx_iovec_t vec; |
| 21 | struct iovec iovs[NGX_IOVS_PREALLOCATE]; |
| 22 | |
| 23 | wev = c->write; |
| 24 | |
| 25 | if (!wev->ready) { |
| 26 | return in; |
| 27 | } |
| 28 | |
| 29 | #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_FSTACK) |
| 30 | |
| 31 | if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { |
| 32 | (void) ngx_connection_error(c, wev->kq_errno, |
| 33 | "kevent() reported about an closed connection"); |
| 34 | wev->error = 1; |
| 35 | return NGX_CHAIN_ERROR; |
| 36 | } |
| 37 | |
| 38 | #endif |
| 39 | |
| 40 | /* the maximum limit size is the maximum size_t value - the page size */ |
| 41 | |
| 42 | if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { |
| 43 | limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; |
| 44 | } |
| 45 | |
| 46 | send = 0; |
| 47 | |
| 48 | vec.iovs = iovs; |
| 49 | vec.nalloc = NGX_IOVS_PREALLOCATE; |
| 50 | |
| 51 | for ( ;; ) { |
| 52 | prev_send = send; |
| 53 | |
| 54 | /* create the iovec and coalesce the neighbouring bufs */ |
| 55 | |
| 56 | cl = ngx_output_chain_to_iovec(&vec, in, limit - send, c->log); |
| 57 | |
| 58 | if (cl == NGX_CHAIN_ERROR) { |
| 59 | return NGX_CHAIN_ERROR; |
| 60 | } |
| 61 | |
| 62 | if (cl && cl->buf->in_file) { |
| 63 | ngx_log_error(NGX_LOG_ALERT, c->log, 0, |
| 64 | "file buf in writev " |
| 65 | "t:%d r:%d f:%d %p %p-%p %p %O-%O", |
| 66 | cl->buf->temporary, |
| 67 | cl->buf->recycled, |
| 68 | cl->buf->in_file, |
| 69 | cl->buf->start, |
| 70 | cl->buf->pos, |
no test coverage detected