comparison src/event/ngx_event_accept.c @ 92:45945fa8b8ba NGINX_0_2_0

nginx 0.2.0 *) The pid-file names used during online upgrade was changed and now is not required a manual rename operation. The old master process adds the ".oldbin" suffix to its pid-file and executes a new binary file. The new master process creates usual pid-file without the ".newbin" suffix. If the master process exits, then old master process renames back its pid-file with the ".oldbin" suffix to the pid-file without suffix. *) Change: the "worker_connections" directive, new name of the "connections" directive; now the directive specifies maximum number of connections, but not maximum socket descriptor number. *) Feature: SSL supports the session cache inside one worker process. *) Feature: the "satisfy_any" directive. *) Change: the ngx_http_access_module and ngx_http_auth_basic_module do not run for subrequests. *) Feature: the "worker_rlimit_nofile" and "worker_rlimit_sigpending" directives. *) Bugfix: if all backend using in load-balancing failed after one error, then nginx did not try do connect to them during 60 seconds. *) Bugfix: in IMAP/POP3 command argument parsing. Thanks to Rob Mueller. *) Bugfix: errors while using SSL in IMAP/POP3 proxy. *) Bugfix: errors while using SSI and gzipping. *) Bugfix: the "Expires" and "Cache-Control" header lines were omitted from the 304 responses. Thanks to Alexandr Kukushkin.
author Igor Sysoev <http://sysoev.ru>
date Fri, 23 Sep 2005 00:00:00 +0400
parents e916a291e9aa
children dad2fe8ecf08
comparison
equal deleted inserted replaced
91:c3eee83ea942 92:45945fa8b8ba
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 10
11 11
12 static void ngx_close_accepted_socket(ngx_socket_t s, ngx_log_t *log); 12 /* the buffer size is enough to hold "struct sockaddr_un" */
13 static u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len); 13 #define NGX_SOCKLEN 512
14
15
16 static void ngx_close_accepted_connection(ngx_connection_t *c);
14 17
15 18
16 void 19 void
17 ngx_event_accept(ngx_event_t *ev) 20 ngx_event_accept(ngx_event_t *ev)
18 { 21 {
19 ngx_uint_t instance; 22 socklen_t sl;
20 #if 0
21 ngx_uint_t accepted;
22 #endif
23 socklen_t len;
24 struct sockaddr *sa;
25 ngx_err_t err; 23 ngx_err_t err;
26 ngx_log_t *log; 24 ngx_log_t *log;
27 ngx_pool_t *pool; 25 ngx_uint_t instance;
28 ngx_socket_t s; 26 ngx_socket_t s;
29 ngx_event_t *rev, *wev; 27 ngx_event_t *rev, *wev;
30 ngx_connection_t *c, *ls; 28 ngx_listening_t *ls;
29 ngx_connection_t *c, *lc;
31 ngx_event_conf_t *ecf; 30 ngx_event_conf_t *ecf;
31 char sa[NGX_SOCKLEN];
32 32
33 ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module); 33 ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
34 34
35 if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { 35 if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
36 ev->available = 1; 36 ev->available = 1;
37 37
38 } else if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) { 38 } else if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) {
39 ev->available = ecf->multi_accept; 39 ev->available = ecf->multi_accept;
40 } 40 }
41 41
42 ls = ev->data; 42 lc = ev->data;
43 ls = lc->listening;
44 ev->ready = 0;
43 45
44 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, 46 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
45 "accept on %V, ready: %d", 47 "accept on %V, ready: %d", &ls->addr_text, ev->available);
46 &ls->listening->addr_text, ev->available);
47
48 ev->ready = 0;
49 pool = NULL;
50 #if 0
51 accepted = 0;
52 #endif
53 48
54 do { 49 do {
55 50 sl = NGX_SOCKLEN;
56 if (pool == NULL) { 51
57 52 s = accept(lc->fd, (struct sockaddr *) sa, &sl);
58 /*
59 * Create the pool before accept() to avoid the copying of
60 * the sockaddr. Although accept() can fail it is uncommon
61 * case and besides the pool can be got from the free pool list.
62 */
63
64 pool = ngx_create_pool(ls->listening->pool_size, ev->log);
65 if (pool == NULL) {
66 return;
67 }
68 }
69
70 sa = ngx_palloc(pool, ls->listening->socklen);
71 if (sa == NULL) {
72 ngx_destroy_pool(pool);
73 return;
74 }
75
76 log = ngx_palloc(pool, sizeof(ngx_log_t));
77 if (log == NULL) {
78 ngx_destroy_pool(pool);
79 return;
80 }
81
82 ngx_memcpy(log, ls->log, sizeof(ngx_log_t));
83 pool->log = log;
84
85 log->data = &ls->listening->addr_text;
86 log->handler = ngx_accept_log_error;
87
88 len = ls->listening->socklen;
89
90 s = accept(ls->fd, sa, &len);
91 53
92 if (s == -1) { 54 if (s == -1) {
93 err = ngx_socket_errno; 55 err = ngx_socket_errno;
94 56
95 if (err == NGX_EAGAIN) { 57 if (err == NGX_EAGAIN) {
96 #if 0
97 if (!(ngx_event_flags & NGX_USE_RTSIG_EVENT))
98 {
99 ngx_log_error(NGX_LOG_NOTICE, log, err,
100 "EAGAIN after %d accepted connection(s)",
101 accepted);
102 }
103 #endif
104
105 ngx_destroy_pool(pool);
106 return; 58 return;
107 } 59 }
108 60
109 ngx_log_error((err == NGX_ECONNABORTED) ? NGX_LOG_CRIT: 61 ngx_log_error((err == NGX_ECONNABORTED) ? NGX_LOG_CRIT:
110 NGX_LOG_ALERT, 62 NGX_LOG_ALERT,
111 ev->log, err, 63 ev->log, err, "accept() failed");
112 "accept() on %V failed", &ls->listening->addr_text);
113 64
114 if (err == NGX_ECONNABORTED) { 65 if (err == NGX_ECONNABORTED) {
115 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { 66 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
116 ev->available--; 67 ev->available--;
117 } 68 }
118 69
119 if (ev->available) { 70 if (ev->available) {
120 /* reuse the previously allocated pool */
121 continue; 71 continue;
122 } 72 }
123 } 73 }
124 74
125 ngx_destroy_pool(pool);
126 return; 75 return;
127 } 76 }
128 77
129 #if (NGX_STAT_STUB) 78 #if (NGX_STAT_STUB)
130 ngx_atomic_inc(ngx_stat_accepted); 79 ngx_atomic_inc(ngx_stat_accepted);
131 ngx_atomic_inc(ngx_stat_active); 80 ngx_atomic_inc(ngx_stat_active);
132 #endif 81 #endif
133 82
134 ngx_accept_disabled = (ngx_uint_t) s + NGX_ACCEPT_THRESHOLD 83 ngx_accept_disabled = NGX_ACCEPT_THRESHOLD
135 - ecf->connections; 84 - ngx_cycle->free_connection_n;
136 85
137 /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */ 86 c = ngx_get_connection(s, ev->log);
138 87
139 if ((ngx_uint_t) s >= ecf->connections) { 88 if (c == NULL) {
140 89 if (ngx_close_socket(s) == -1) {
141 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, 90 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
142 "accept() on %V returned socket #%d while " 91 ngx_close_socket_n " failed");
143 "only %d connections was configured, " 92 }
144 "closing the connection", 93
145 &ls->listening->addr_text, s, ecf->connections);
146
147 ngx_close_accepted_socket(s, log);
148 ngx_destroy_pool(pool);
149 return; 94 return;
150 } 95 }
151 96
97 rev = c->read;
98 wev = c->write;
99
100 ngx_memzero(c, sizeof(ngx_connection_t));
101
102 c->read = rev;
103 c->write = wev;
104 c->fd = s;
105 c->log = ev->log;
106
107 c->pool = ngx_create_pool(ls->pool_size, ev->log);
108 if (c->pool == NULL) {
109 ngx_close_accepted_connection(c);
110 return;
111 }
112
113 c->sockaddr = ngx_palloc(c->pool, sl);
114 if (c->sockaddr == NULL) {
115 ngx_close_accepted_connection(c);
116 return;
117 }
118
119 ngx_memcpy(c->sockaddr, sa, sl);
120
121 log = ngx_palloc(c->pool, sizeof(ngx_log_t));
122 if (log == NULL) {
123 ngx_close_accepted_connection(c);
124 return;
125 }
126
152 /* set a blocking mode for aio and non-blocking mode for others */ 127 /* set a blocking mode for aio and non-blocking mode for others */
153 128
154 if (ngx_inherited_nonblocking) { 129 if (ngx_inherited_nonblocking) {
155 if ((ngx_event_flags & NGX_USE_AIO_EVENT)) { 130 if (ngx_event_flags & NGX_USE_AIO_EVENT) {
156 if (ngx_blocking(s) == -1) { 131 if (ngx_blocking(s) == -1) {
157 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, 132 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
158 ngx_blocking_n " failed"); 133 ngx_blocking_n " failed");
159 134 ngx_close_accepted_connection(c);
160 ngx_close_accepted_socket(s, log);
161 ngx_destroy_pool(pool);
162 return; 135 return;
163 } 136 }
164 } 137 }
165 138
166 } else { 139 } else {
167 if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) { 140 if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) {
168 if (ngx_nonblocking(s) == -1) { 141 if (ngx_nonblocking(s) == -1) {
169 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, 142 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
170 ngx_nonblocking_n " failed"); 143 ngx_nonblocking_n " failed");
171 144 ngx_close_accepted_connection(c);
172 ngx_close_accepted_socket(s, log);
173 ngx_destroy_pool(pool);
174 return; 145 return;
175 } 146 }
176 } 147 }
177 } 148 }
178 149
179 #if (NGX_WIN32) 150 *log = ls->log;
180 /* 151
181 * Winsock assignes a socket number divisible by 4 152 c->recv = ngx_recv;
182 * so to find a connection we divide a socket number by 4. 153 c->send = ngx_send;
183 */ 154 c->send_chain = ngx_send_chain;
184 155
185 if (s % 4) { 156 c->log = log;
186 ngx_log_error(NGX_LOG_EMERG, ev->log, 0, 157 c->pool->log = log;
187 "accept() on %V returned socket #%d, " 158
188 "not divisible by 4", 159 c->listening = ls;
189 &ls->listening->addr_text, s); 160 c->socklen = sl;
190 exit(1); 161
191 } 162 c->unexpected_eof = 1;
192 163
193 c = &ngx_cycle->connections[s / 4]; 164 c->ctx = lc->ctx;
194 rev = &ngx_cycle->read_events[s / 4]; 165 c->servers = lc->servers;
195 wev = &ngx_cycle->write_events[s / 4];
196 #else
197 c = &ngx_cycle->connections[s];
198 rev = &ngx_cycle->read_events[s];
199 wev = &ngx_cycle->write_events[s];
200 #endif
201 166
202 instance = rev->instance; 167 instance = rev->instance;
203
204 #if (NGX_THREADS)
205
206 if (*(&c->lock)) {
207 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
208 "spinlock in accept, fd:%d", s);
209 ngx_spinlock(&c->lock, 1000);
210 ngx_unlock(&c->lock);
211 }
212
213 #endif
214 168
215 ngx_memzero(rev, sizeof(ngx_event_t)); 169 ngx_memzero(rev, sizeof(ngx_event_t));
216 ngx_memzero(wev, sizeof(ngx_event_t)); 170 ngx_memzero(wev, sizeof(ngx_event_t));
217 ngx_memzero(c, sizeof(ngx_connection_t));
218
219 c->pool = pool;
220
221 c->listening = ls->listening;
222 c->sockaddr = sa;
223 c->socklen = len;
224 171
225 rev->instance = !instance; 172 rev->instance = !instance;
226 wev->instance = !instance; 173 wev->instance = !instance;
227 174
228 rev->index = NGX_INVALID_INDEX; 175 rev->index = NGX_INVALID_INDEX;
229 wev->index = NGX_INVALID_INDEX; 176 wev->index = NGX_INVALID_INDEX;
230 177
231 rev->data = c; 178 rev->data = c;
232 wev->data = c; 179 wev->data = c;
233
234 c->read = rev;
235 c->write = wev;
236
237 c->fd = s;
238 c->unexpected_eof = 1;
239 180
240 wev->write = 1; 181 wev->write = 1;
241 wev->ready = 1; 182 wev->ready = 1;
242 183
243 if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) { 184 if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {
250 #if (NGX_HAVE_KQUEUE) 191 #if (NGX_HAVE_KQUEUE)
251 rev->available = 1; 192 rev->available = 1;
252 #endif 193 #endif
253 } 194 }
254 195
255 c->ctx = ls->ctx;
256 c->servers = ls->servers;
257
258 c->recv = ngx_recv;
259 c->send = ngx_send;
260 c->send_chain = ngx_send_chain;
261
262 c->log = log;
263 rev->log = log; 196 rev->log = log;
264 wev->log = log; 197 wev->log = log;
265 198
266 /* 199 /*
267 * TODO: MT: - atomic increment (x86: lock xadd) 200 * TODO: MT: - atomic increment (x86: lock xadd)
283 wev->lock = &c->lock; 216 wev->lock = &c->lock;
284 rev->own_lock = &c->lock; 217 rev->own_lock = &c->lock;
285 wev->own_lock = &c->lock; 218 wev->own_lock = &c->lock;
286 #endif 219 #endif
287 220
288 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, 221 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
289 "accept: fd:%d c:%d", s, c->number); 222 "accept: fd:%d c:%d", s, c->number);
290 223
291 if (c->listening->addr_ntop) { 224 if (ls->addr_ntop) {
292 c->addr_text.data = ngx_palloc(c->pool, 225 c->addr_text.data = ngx_palloc(c->pool, ls->addr_text_max_len);
293 c->listening->addr_text_max_len);
294 if (c->addr_text.data == NULL) { 226 if (c->addr_text.data == NULL) {
295 ngx_close_accepted_socket(s, log); 227 ngx_close_accepted_connection(c);
296 ngx_destroy_pool(pool);
297 return; 228 return;
298 } 229 }
299 230
300 c->addr_text.len = ngx_sock_ntop(c->listening->family, c->sockaddr, 231 c->addr_text.len = ngx_sock_ntop(ls->family, c->sockaddr,
301 c->addr_text.data, 232 c->addr_text.data,
302 c->listening->addr_text_max_len); 233 ls->addr_text_max_len);
303 if (c->addr_text.len == 0) { 234 if (c->addr_text.len == 0) {
304 ngx_close_accepted_socket(s, log); 235 ngx_close_accepted_connection(c);
305 ngx_destroy_pool(pool);
306 return; 236 return;
307 } 237 }
308 } 238 }
309 239
310 #if (NGX_DEBUG) 240 #if (NGX_DEBUG)
326 } 256 }
327 #endif 257 #endif
328 258
329 if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) { 259 if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
330 if (ngx_add_conn(c) == NGX_ERROR) { 260 if (ngx_add_conn(c) == NGX_ERROR) {
331 ngx_close_accepted_socket(s, log); 261 ngx_close_accepted_connection(c);
332 ngx_destroy_pool(pool);
333 return; 262 return;
334 } 263 }
335 } 264 }
336
337 pool = NULL;
338 265
339 log->data = NULL; 266 log->data = NULL;
340 log->handler = NULL; 267 log->handler = NULL;
341 268
342 ls->listening->handler(c); 269 ls->handler(c);
343 270
344 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { 271 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
345 ev->available--; 272 ev->available--;
346 } 273 }
347
348 #if 0
349 accepted++;
350 #endif
351 274
352 } while (ev->available); 275 } while (ev->available);
353 } 276 }
354 277
355 278
387 310
388 311
389 ngx_int_t 312 ngx_int_t
390 ngx_enable_accept_events(ngx_cycle_t *cycle) 313 ngx_enable_accept_events(ngx_cycle_t *cycle)
391 { 314 {
392 ngx_uint_t i; 315 ngx_uint_t i;
393 ngx_listening_t *s; 316 ngx_listening_t *ls;
394 317 ngx_connection_t *c;
395 s = cycle->listening.elts; 318
319 ls = cycle->listening.elts;
396 for (i = 0; i < cycle->listening.nelts; i++) { 320 for (i = 0; i < cycle->listening.nelts; i++) {
397 321
398 /* 322 c = ls[i].connection;
399 * we do not need to handle the Winsock sockets here (divide a socket
400 * number by 4) because this function would never called
401 * in the Winsock environment
402 */
403 323
404 if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { 324 if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
405 if (ngx_add_conn(&cycle->connections[s[i].fd]) == NGX_ERROR) { 325 if (ngx_add_conn(c) == NGX_ERROR) {
406 return NGX_ERROR; 326 return NGX_ERROR;
407 } 327 }
408 328
409 } else { 329 } else {
410 if (ngx_add_event(&cycle->read_events[s[i].fd], NGX_READ_EVENT, 0) 330 if (ngx_add_event(c->read, NGX_READ_EVENT, 0) == NGX_ERROR) {
411 == NGX_ERROR) 331 return NGX_ERROR;
332 }
333 }
334 }
335
336 return NGX_OK;
337 }
338
339
340 ngx_int_t
341 ngx_disable_accept_events(ngx_cycle_t *cycle)
342 {
343 ngx_uint_t i;
344 ngx_listening_t *ls;
345 ngx_connection_t *c;
346
347 ls = cycle->listening.elts;
348 for (i = 0; i < cycle->listening.nelts; i++) {
349
350 c = ls[i].connection;
351
352 if (!c->read->active) {
353 continue;
354 }
355
356 if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
357 if (ngx_del_conn(c, NGX_DISABLE_EVENT) == NGX_ERROR) {
358 return NGX_ERROR;
359 }
360
361 } else {
362 if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)
363 == NGX_ERROR)
412 { 364 {
413 return NGX_ERROR; 365 return NGX_ERROR;
414 } 366 }
415 } 367 }
416 } 368 }
417 369
418 return NGX_OK; 370 return NGX_OK;
419 } 371 }
420 372
421 373
422 ngx_int_t
423 ngx_disable_accept_events(ngx_cycle_t *cycle)
424 {
425 ngx_uint_t i;
426 ngx_listening_t *s;
427
428 s = cycle->listening.elts;
429 for (i = 0; i < cycle->listening.nelts; i++) {
430
431 /*
432 * we do not need to handle the Winsock sockets here (divide a socket
433 * number by 4) because this function would never called
434 * in the Winsock environment
435 */
436
437 if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
438 if (!cycle->connections[s[i].fd].read->active) {
439 continue;
440 }
441
442 if (ngx_del_conn(&cycle->connections[s[i].fd], NGX_DISABLE_EVENT)
443 == NGX_ERROR)
444 {
445 return NGX_ERROR;
446 }
447
448 } else {
449 if (!cycle->read_events[s[i].fd].active) {
450 continue;
451 }
452
453 if (ngx_del_event(&cycle->read_events[s[i].fd], NGX_READ_EVENT,
454 NGX_DISABLE_EVENT) == NGX_ERROR)
455 {
456 return NGX_ERROR;
457 }
458 }
459 }
460
461 return NGX_OK;
462 }
463
464
465 static void 374 static void
466 ngx_close_accepted_socket(ngx_socket_t s, ngx_log_t *log) 375 ngx_close_accepted_connection(ngx_connection_t *c)
467 { 376 {
468 if (ngx_close_socket(s) == -1) { 377 ngx_socket_t fd;
469 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, 378
379 ngx_free_connection(c);
380
381 fd = c->fd;
382 c->fd = (ngx_socket_t) -1;
383
384 if (ngx_close_socket(fd) == -1) {
385 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
470 ngx_close_socket_n " failed"); 386 ngx_close_socket_n " failed");
387 }
388
389 if (c->pool) {
390 ngx_destroy_pool(c->pool);
471 } 391 }
472 392
473 #if (NGX_STAT_STUB) 393 #if (NGX_STAT_STUB)
474 ngx_atomic_dec(ngx_stat_active); 394 ngx_atomic_dec(ngx_stat_active);
475 #endif 395 #endif
476 } 396 }
477 397
478 398
479 static u_char * 399 u_char *
480 ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len) 400 ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len)
481 { 401 {
482 return ngx_snprintf(buf, len, " while accept() on %V", log->data); 402 return ngx_snprintf(buf, len, " while accepting new connection on %V",
483 } 403 log->data);
404 }