comparison src/os/unix/ngx_linux_sendfile_chain.c @ 22:8b6db3bda591 NGINX_0_1_11

nginx 0.1.11 *) 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 <http://sysoev.ru>
date Thu, 02 Dec 2004 00:00:00 +0300
parents 6f8b0dc0f8dd
children 45fe5b98a9de
comparison
equal deleted inserted replaced
21:4eeb9cfef970 22:8b6db3bda591
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 }