Mercurial > hg > nginx-quic
comparison src/os/unix/ngx_linux_sendfile_chain.c @ 473:8e8f3af115b5 release-0.1.11
nginx-0.1.11-RELEASE import
*) Feature: the worker_priority directive.
*) Change: both tcp_nopush and tcp_nodelay directives affect the
transferred response.
*) Bugfix: nginx did not call initgroups().
Thanks to Andrew Sitnikov and Andrei Nigmatulin.
*) Change: now the ngx_http_autoindex_module shows the file size in the
bytes.
*) Bugfix: the ngx_http_autoindex_module returned the 500 error if the
broken symlink was in a directory.
*) Bugfix: the files bigger than 4G could not be transferred using
sendfile.
*) Bugfix: if the backend was resolved to several backends and there
was an error while the response waiting then process may got caught
in an endless loop.
*) Bugfix: the worker process may exit with the "unknown cycle" message
when the /dev/poll method was used.
*) Bugfix: "close() channel failed" errors.
*) Bugfix: the autodetection of the "nobody" and "nogroup" groups.
*) Bugfix: the send_lowat directive did not work on Linux.
*) Bugfix: the segmentation fault occurred if there was no events
section in configuration.
*) Bugfix: nginx could not be built on OpenBSD.
*) Bugfix: the double slashes in "://" in the URI were converted to
":/".
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 02 Dec 2004 18:40:46 +0000 |
parents | 2ff194b74f1e |
children | ad1e9ebf93bb |
comparison
equal
deleted
inserted
replaced
472:a004b617422d | 473:8e8f3af115b5 |
---|---|
23 | 23 |
24 | 24 |
25 ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, | 25 ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, |
26 off_t limit) | 26 off_t limit) |
27 { | 27 { |
28 int rc; | 28 int rc, tcp_nodelay; |
29 u_char *prev; | 29 u_char *prev; |
30 off_t fprev, send, sprev, aligned; | 30 off_t size, send, prev_send, aligned, sent, fprev; |
31 size_t fsize; | 31 size_t file_size; |
32 ssize_t size, sent; | |
33 ngx_uint_t eintr, complete; | 32 ngx_uint_t eintr, complete; |
34 ngx_err_t err; | 33 ngx_err_t err; |
35 ngx_buf_t *file; | 34 ngx_buf_t *file; |
36 ngx_array_t header; | 35 ngx_array_t header; |
37 ngx_event_t *wev; | 36 ngx_event_t *wev; |
47 | 46 |
48 if (!wev->ready) { | 47 if (!wev->ready) { |
49 return in; | 48 return in; |
50 } | 49 } |
51 | 50 |
51 | |
52 /* the maximum limit size is the maximum size_t value - the page size */ | |
53 | |
54 if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { | |
55 limit = MAX_SIZE_T_VALUE - ngx_pagesize; | |
56 } | |
57 | |
58 | |
52 send = 0; | 59 send = 0; |
53 | 60 |
54 header.elts = headers; | 61 header.elts = headers; |
55 header.size = sizeof(struct iovec); | 62 header.size = sizeof(struct iovec); |
56 header.nalloc = NGX_HEADERS; | 63 header.nalloc = NGX_HEADERS; |
57 header.pool = c->pool; | 64 header.pool = c->pool; |
58 | 65 |
59 for ( ;; ) { | 66 for ( ;; ) { |
60 file = NULL; | 67 file = NULL; |
61 fsize = 0; | 68 file_size = 0; |
62 eintr = 0; | 69 eintr = 0; |
63 complete = 0; | 70 complete = 0; |
64 sprev = send; | 71 prev_send = send; |
65 | 72 |
66 header.nelts = 0; | 73 header.nelts = 0; |
67 | 74 |
68 prev = NULL; | 75 prev = NULL; |
69 iov = NULL; | 76 iov = NULL; |
87 if (send + size > limit) { | 94 if (send + size > limit) { |
88 size = limit - send; | 95 size = limit - send; |
89 } | 96 } |
90 | 97 |
91 if (prev == cl->buf->pos) { | 98 if (prev == cl->buf->pos) { |
92 iov->iov_len += size; | 99 iov->iov_len += (size_t) size; |
93 | 100 |
94 } else { | 101 } else { |
95 if (!(iov = ngx_array_push(&header))) { | 102 if (!(iov = ngx_array_push(&header))) { |
96 return NGX_CHAIN_ERROR; | 103 return NGX_CHAIN_ERROR; |
97 } | 104 } |
98 | 105 |
99 iov->iov_base = (void *) cl->buf->pos; | 106 iov->iov_base = (void *) cl->buf->pos; |
100 iov->iov_len = size; | 107 iov->iov_len = (size_t) size; |
101 } | 108 } |
102 | 109 |
103 prev = cl->buf->pos + size; | 110 prev = cl->buf->pos + (size_t) size; |
104 send += size; | 111 send += size; |
105 } | 112 } |
106 | 113 |
107 /* set TCP_CORK if there is a header before a file */ | 114 /* set TCP_CORK if there is a header before a file */ |
108 | 115 |
109 if (c->tcp_nopush == NGX_TCP_NOPUSH_UNSET | 116 if (c->tcp_nopush == NGX_TCP_NOPUSH_UNSET |
110 && header.nelts != 0 | 117 && header.nelts != 0 |
111 && cl | 118 && cl |
112 && cl->buf->in_file) | 119 && cl->buf->in_file) |
113 { | 120 { |
114 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { | 121 |
115 err = ngx_errno; | 122 /* the TCP_CORK and TCP_NODELAY are mutually exclusive */ |
116 | 123 |
117 /* | 124 if (c->tcp_nodelay) { |
118 * there is a tiny chance to be interrupted, however | 125 |
119 * we continue a processing without the TCP_CORK | 126 tcp_nodelay = 0; |
120 */ | 127 |
121 | 128 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, |
122 if (err != NGX_EINTR) { | 129 (const void *) &tcp_nodelay, sizeof(int)) == -1) |
123 wev->error = 1; | 130 { |
124 ngx_connection_error(c, err, ngx_tcp_nopush_n " failed"); | 131 err = ngx_errno; |
125 return NGX_CHAIN_ERROR; | 132 |
126 } | 133 /* |
127 | 134 * there is a tiny chance to be interrupted, however |
128 } else { | 135 * we continue a processing with the TCP_NODELAY |
129 c->tcp_nopush = NGX_TCP_NOPUSH_SET; | 136 * and without the TCP_CORK |
130 | 137 */ |
131 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | 138 |
132 "tcp_nopush"); | 139 if (err != NGX_EINTR) { |
140 wev->error = 1; | |
141 ngx_connection_error(c, ngx_socket_errno, | |
142 "setsockopt(TCP_NODELAY) failed"); | |
143 return NGX_CHAIN_ERROR; | |
144 } | |
145 | |
146 } else { | |
147 c->tcp_nodelay = 0; | |
148 | |
149 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
150 "no tcp_nodelay"); | |
151 } | |
152 } | |
153 | |
154 if (!c->tcp_nodelay) { | |
155 | |
156 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { | |
157 err = ngx_errno; | |
158 | |
159 /* | |
160 * there is a tiny chance to be interrupted, however | |
161 * we continue a processing without the TCP_CORK | |
162 */ | |
163 | |
164 if (err != NGX_EINTR) { | |
165 wev->error = 1; | |
166 ngx_connection_error(c, err, | |
167 ngx_tcp_nopush_n " failed"); | |
168 return NGX_CHAIN_ERROR; | |
169 } | |
170 | |
171 } else { | |
172 c->tcp_nopush = NGX_TCP_NOPUSH_SET; | |
173 | |
174 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
175 "tcp_nopush"); | |
176 } | |
133 } | 177 } |
134 } | 178 } |
135 | 179 |
136 /* get the file buf */ | 180 /* get the file buf */ |
137 | 181 |
139 file = cl->buf; | 183 file = cl->buf; |
140 | 184 |
141 /* coalesce the neighbouring file bufs */ | 185 /* coalesce the neighbouring file bufs */ |
142 | 186 |
143 do { | 187 do { |
144 size = (size_t) (cl->buf->file_last - cl->buf->file_pos); | 188 size = cl->buf->file_last - cl->buf->file_pos; |
145 | 189 |
146 if (send + size > limit) { | 190 if (send + size > limit) { |
147 size = limit - send; | 191 size = limit - send; |
148 | 192 |
149 aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) | 193 aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) |
152 if (aligned <= cl->buf->file_last) { | 196 if (aligned <= cl->buf->file_last) { |
153 size = aligned - cl->buf->file_pos; | 197 size = aligned - cl->buf->file_pos; |
154 } | 198 } |
155 } | 199 } |
156 | 200 |
157 fsize += size; | 201 file_size += (size_t) size; |
158 send += size; | 202 send += size; |
159 fprev = cl->buf->file_pos + size; | 203 fprev = cl->buf->file_pos + size; |
160 cl = cl->next; | 204 cl = cl->next; |
161 | 205 |
162 } while (cl | 206 } while (cl |
170 #if (NGX_HAVE_SENDFILE64) | 214 #if (NGX_HAVE_SENDFILE64) |
171 offset = file->file_pos; | 215 offset = file->file_pos; |
172 #else | 216 #else |
173 offset = (int32_t) file->file_pos; | 217 offset = (int32_t) file->file_pos; |
174 #endif | 218 #endif |
175 rc = sendfile(c->fd, file->file->fd, &offset, fsize); | 219 rc = sendfile(c->fd, file->file->fd, &offset, file_size); |
176 | 220 |
177 if (rc == -1) { | 221 if (rc == -1) { |
178 err = ngx_errno; | 222 err = ngx_errno; |
179 | 223 |
180 if (err == NGX_EAGAIN || err == NGX_EINTR) { | 224 if (err == NGX_EAGAIN || err == NGX_EINTR) { |
193 } | 237 } |
194 | 238 |
195 sent = rc > 0 ? rc : 0; | 239 sent = rc > 0 ? rc : 0; |
196 | 240 |
197 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, | 241 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, |
198 "sendfile: %d, @%O %z:%uz", | 242 "sendfile: %d, @%O %O:%uz", |
199 rc, file->file_pos, sent, fsize); | 243 rc, file->file_pos, sent, file_size); |
200 | 244 |
201 } else { | 245 } else { |
202 rc = writev(c->fd, header.elts, header.nelts); | 246 rc = writev(c->fd, header.elts, header.nelts); |
203 | 247 |
204 if (rc == -1) { | 248 if (rc == -1) { |
219 } | 263 } |
220 } | 264 } |
221 | 265 |
222 sent = rc > 0 ? rc : 0; | 266 sent = rc > 0 ? rc : 0; |
223 | 267 |
224 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent); | 268 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O", sent); |
225 } | 269 } |
226 | 270 |
227 if (send - sprev == sent) { | 271 if (send - prev_send == sent) { |
228 complete = 1; | 272 complete = 1; |
229 } | 273 } |
230 | 274 |
231 c->sent += sent; | 275 c->sent += sent; |
232 | 276 |
255 | 299 |
256 continue; | 300 continue; |
257 } | 301 } |
258 | 302 |
259 if (ngx_buf_in_memory(cl->buf)) { | 303 if (ngx_buf_in_memory(cl->buf)) { |
260 cl->buf->pos += sent; | 304 cl->buf->pos += (size_t) sent; |
261 } | 305 } |
262 | 306 |
263 if (cl->buf->in_file) { | 307 if (cl->buf->in_file) { |
264 cl->buf->file_pos += sent; | 308 cl->buf->file_pos += sent; |
265 } | 309 } |