comparison src/core/ngx_cycle.c @ 218:05592fd7a436

nginx-0.0.1-2004-01-05-23:55:48 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 05 Jan 2004 20:55:48 +0000
parents
children f57597ec5249
comparison
equal deleted inserted replaced
217:c5d1cdcb04ec 218:05592fd7a436
1
2 #include <ngx_config.h>
3 #include <ngx_core.h>
4 #include <ngx_event.h>
5 /* STUB */
6 #include <nginx.h>
7
8
9 static void ngx_clean_old_cycles(ngx_event_t *ev);
10
11
12 volatile ngx_cycle_t *ngx_cycle;
13 ngx_array_t ngx_old_cycles;
14
15 static ngx_pool_t *ngx_temp_pool;
16 static ngx_event_t ngx_cleaner_event;
17
18
19 /* STUB NAME */
20 static ngx_connection_t dumb;
21 /* STUB */
22
23
24 ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle)
25 {
26 ngx_int_t i, n, failed;
27 ngx_str_t conf_file;
28 ngx_log_t *log;
29 ngx_conf_t conf;
30 ngx_pool_t *pool;
31 ngx_cycle_t *cycle, **old;
32 ngx_socket_t fd;
33 ngx_open_file_t *file;
34 ngx_listening_t *ls, *nls;
35
36 log = old_cycle->log;
37
38 if (!(pool = ngx_create_pool(16 * 1024, log))) {
39 return NULL;
40 }
41
42 if (!(cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)))) {
43 ngx_destroy_pool(pool);
44 return NULL;
45 }
46 cycle->pool = pool;
47
48 cycle->old_cycle = old_cycle;
49
50
51 n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10;
52 if (!(cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)))) {
53 ngx_destroy_pool(pool);
54 return NULL;
55 }
56 cycle->pathes.nelts = 0;
57 cycle->pathes.size = sizeof(ngx_path_t *);
58 cycle->pathes.nalloc = n;
59 cycle->pathes.pool = pool;
60
61
62 n = old_cycle->open_files.nelts ? old_cycle->open_files.nelts : 20;
63 cycle->open_files.elts = ngx_pcalloc(pool, n * sizeof(ngx_open_file_t));
64 if (cycle->open_files.elts == NULL) {
65 ngx_destroy_pool(pool);
66 return NULL;
67 }
68 cycle->open_files.nelts = 0;
69 cycle->open_files.size = sizeof(ngx_open_file_t);
70 cycle->open_files.nalloc = n;
71 cycle->open_files.pool = pool;
72
73
74 if (!(cycle->log = ngx_log_create_errlog(cycle, NULL))) {
75 ngx_destroy_pool(pool);
76 return NULL;
77 }
78
79
80 n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
81 cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
82 if (cycle->listening.elts == NULL) {
83 ngx_destroy_pool(pool);
84 return NULL;
85 }
86 cycle->listening.nelts = 0;
87 cycle->listening.size = sizeof(ngx_listening_t);
88 cycle->listening.nalloc = n;
89 cycle->listening.pool = pool;
90
91
92 cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
93 if (cycle->conf_ctx == NULL) {
94 ngx_destroy_pool(pool);
95 return NULL;
96 }
97
98
99 if (ngx_core_module.init_module(cycle) == NGX_ERROR) {
100 ngx_destroy_pool(pool);
101 return NULL;
102 }
103
104
105 ngx_memzero(&conf, sizeof(ngx_conf_t));
106 /* STUB: init array ? */
107 conf.args = ngx_create_array(pool, 10, sizeof(ngx_str_t));
108 if (conf.args == NULL) {
109 ngx_destroy_pool(pool);
110 return NULL;
111 }
112
113 conf.ctx = cycle->conf_ctx;
114 conf.cycle = cycle;
115 /* STUB */ conf.pool = cycle->pool;
116 conf.log = log;
117 conf.module_type = NGX_CORE_MODULE;
118 conf.cmd_type = NGX_MAIN_CONF;
119
120 conf_file.len = sizeof(NGINX_CONF) - 1;
121 conf_file.data = NGINX_CONF;
122
123 if (ngx_conf_parse(&conf, &conf_file) != NGX_CONF_OK) {
124 ngx_destroy_pool(pool);
125 return NULL;
126 }
127
128
129 failed = 0;
130
131 file = cycle->open_files.elts;
132 for (i = 0; i < cycle->open_files.nelts; i++) {
133 if (file[i].name.data == NULL) {
134 continue;
135 }
136
137 file[i].fd = ngx_open_file(file[i].name.data,
138 NGX_FILE_RDWR,
139 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
140
141 ngx_log_debug(log, "OPEN: %d:%s" _ file[i].fd _ file[i].name.data);
142
143 if (file[i].fd == NGX_INVALID_FILE) {
144 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
145 ngx_open_file_n " \"%s\" failed",
146 file[i].name.data);
147 failed = 1;
148 break;
149 }
150
151 #if (WIN32)
152 if (ngx_file_append_mode(file[i].fd) == NGX_ERROR) {
153 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
154 ngx_file_append_mode_n " \"%s\" failed",
155 file[i].name.data);
156 failed = 1;
157 break;
158 }
159 #endif
160 }
161
162 if (!failed) {
163 if (old_cycle->listening.nelts) {
164 ls = old_cycle->listening.elts;
165 for (i = 0; i < old_cycle->listening.nelts; i++) {
166 ls[i].remain = 0;
167 }
168
169 nls = cycle->listening.elts;
170 for (n = 0; n < cycle->listening.nelts; n++) {
171 for (i = 0; i < old_cycle->listening.nelts; i++) {
172 if (ls[i].ignore) {
173 continue;
174 }
175
176 ngx_log_error(NGX_LOG_INFO, log, 0,
177 "%X, %X",
178 *(int *) ls[i].sockaddr,
179 *(int *) nls[n].sockaddr);
180
181 if (ngx_memcmp(nls[n].sockaddr,
182 ls[i].sockaddr, ls[i].socklen) == 0)
183 {
184 fd = ls[i].fd;
185 #if (WIN32)
186 /*
187 * Winsock assignes a socket number divisible by 4 so
188 * to find a connection we divide a socket number by 4.
189 */
190
191 fd /= 4;
192 #endif
193 if (fd >= (ngx_socket_t) cycle->connection_n) {
194 ngx_log_error(NGX_LOG_EMERG, log, 0,
195 "%d connections is not enough to hold "
196 "an open listening socket on %s, "
197 "required at least %d connections",
198 cycle->connection_n,
199 ls[i].addr_text.data, fd);
200 failed = 1;
201 break;
202 }
203
204 nls[n].fd = ls[i].fd;
205 nls[i].remain = 1;
206 ls[i].remain = 1;
207 break;
208 }
209 }
210
211 if (nls[n].fd == -1) {
212 nls[n].new = 1;
213 }
214 }
215
216 } else {
217 ls = cycle->listening.elts;
218 for (i = 0; i < cycle->listening.nelts; i++) {
219 ls[i].new = 1;
220 }
221 }
222
223 if (!failed) {
224 if (ngx_open_listening_sockets(cycle) == NGX_ERROR) {
225 failed = 1;
226 }
227 }
228 }
229
230 if (failed) {
231
232 /* rollback the new cycle configuration */
233
234 file = cycle->open_files.elts;
235 for (i = 0; i < cycle->open_files.nelts; i++) {
236 if (file[i].fd == NGX_INVALID_FILE) {
237 continue;
238 }
239
240 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
241 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
242 ngx_close_file_n " \"%s\" failed",
243 file[i].name.data);
244 }
245 }
246
247 ls = cycle->listening.elts;
248 for (i = 0; i < cycle->listening.nelts; i++) {
249 if (ls[i].new && ls[i].fd == -1) {
250 continue;
251 }
252
253 if (ngx_close_socket(ls[i].fd) == -1) {
254 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
255 ngx_close_socket_n " %s failed",
256 ls[i].addr_text.data);
257 }
258 }
259
260 ngx_destroy_pool(pool);
261 return NULL;
262 }
263
264 /* commit the new cycle configuration */
265
266 pool->log = cycle->log;
267
268
269 for (i = 0; ngx_modules[i]; i++) {
270 if (ngx_modules[i]->init_module) {
271 if (ngx_modules[i]->init_module(cycle) == NGX_ERROR) {
272 /* fatal */
273 exit(1);
274 }
275 }
276 }
277
278 /* close and delete stuff that lefts from an old cycle */
279
280 /* close the unneeded listening sockets */
281
282 ls = old_cycle->listening.elts;
283 for (i = 0; i < old_cycle->listening.nelts; i++) {
284 if (ls[i].remain) {
285 continue;
286 }
287
288 if (ngx_close_socket(ls[i].fd) == -1) {
289 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
290 ngx_close_socket_n " %s failed",
291 ls[i].addr_text.data);
292 }
293 }
294
295
296 /* close the unneeded open files */
297
298 file = old_cycle->open_files.elts;
299 for (i = 0; i < old_cycle->open_files.nelts; i++) {
300 if (file[i].fd == NGX_INVALID_FILE) {
301 continue;
302 }
303
304 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
305 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
306 ngx_close_file_n " \"%s\" failed",
307 file[i].name.data);
308 }
309 }
310
311 if (old_cycle->connections == NULL) {
312 /* an old cycle is an init cycle */
313 ngx_destroy_pool(old_cycle->pool);
314 return cycle;
315 }
316
317 if (ngx_master) {
318 ngx_destroy_pool(old_cycle->pool);
319 return cycle;
320 }
321
322 if (ngx_temp_pool == NULL) {
323 ngx_temp_pool = ngx_create_pool(128, cycle->log);
324 if (ngx_temp_pool == NULL) {
325 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
326 "can not create ngx_temp_pool");
327 exit(1);
328 }
329
330 n = 10;
331 ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool,
332 n * sizeof(ngx_cycle_t *));
333 if (ngx_old_cycles.elts == NULL) {
334 exit(1);
335 }
336 ngx_old_cycles.nelts = 0;
337 ngx_old_cycles.size = sizeof(ngx_cycle_t *);
338 ngx_old_cycles.nalloc = n;
339 ngx_old_cycles.pool = ngx_temp_pool;
340
341 ngx_cleaner_event.event_handler = ngx_clean_old_cycles;
342 ngx_cleaner_event.log = cycle->log;
343 ngx_cleaner_event.data = &dumb;
344 dumb.fd = (ngx_socket_t) -1;
345 }
346
347 ngx_temp_pool->log = cycle->log;
348
349 old = ngx_push_array(&ngx_old_cycles);
350 if (old == NULL) {
351 exit(1);
352 }
353 *old = old_cycle;
354
355 if (!ngx_cleaner_event.timer_set) {
356 ngx_add_timer(&ngx_cleaner_event, 30000);
357 ngx_cleaner_event.timer_set = 1;
358 }
359
360 return cycle;
361 }
362
363
364 #if 0
365
366
367 static ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle, char **envp)
368 {
369 char *p, *v;
370 ngx_socket_t s;
371 ngx_listening_t *ls;
372 struct sockaddr_in *addr_in;
373
374 for ( /* void */ ; *envp; envp++) {
375 if (ngx_strncmp(*envp, NGINX_VAR, NGINX_VAR_LEN) != 0) {
376 continue;
377 }
378
379 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
380 "using inherited sockets from \"%s\"", *envp);
381
382 ngx_init_array(cycle->listening, cycle->pool,
383 10, sizeof(ngx_listening_t), NGX_ERROR);
384
385 for (p = *envp + NGINX_VAR_LEN, v = p; *p; p++) {
386 if (*p == ':' || *p == ';') {
387 s = ngx_atoi(v, p - v);
388 if (s == NGX_ERROR) {
389 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
390 "invalid socket number \"%s\" "
391 "in NGINX enviroment variable, "
392 "ignoring the rest of the variable", v);
393 break;
394 }
395 v = p + 1;
396
397 if (!(ls = ngx_push_array(&cycle->listening))) {
398 return NGX_ERROR;
399 }
400
401 ls->fd = s;
402
403 /* AF_INET only */
404
405 ls->sockaddr = ngx_palloc(cycle->pool,
406 sizeof(struct sockaddr_in));
407 if (ls->sockaddr == NULL) {
408 return NGX_ERROR;
409 }
410
411 ls->socklen = sizeof(struct sockaddr_in);
412 if (getsockname(s, ls->sockaddr, &ls->socklen) == -1) {
413 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
414 "getsockname() of the inherited "
415 "socket #%d failed", s);
416 ls->ignore = 1;
417 continue;
418 }
419
420 addr_in = (struct sockaddr_in *) ls->sockaddr;
421
422 if (addr_in->sin_family != AF_INET) {
423 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
424 "the inherited socket #%d has "
425 "unsupported family", s);
426 ls->ignore = 1;
427 continue;
428 }
429 ls->addr_text_max_len = INET_ADDRSTRLEN;
430
431 ls->addr_text.data = ngx_palloc(cycle->pool,
432 ls->addr_text_max_len);
433 if (ls->addr_text.data == NULL) {
434 return NGX_ERROR;
435 }
436
437 addr_in->sin_len = 0;
438
439 ls->family = addr_in->sin_family;
440 ls->addr_text.len = ngx_sock_ntop(ls->family, ls->sockaddr,
441 ls->addr_text.data,
442 ls->addr_text_max_len);
443 if (ls->addr_text.len == 0) {
444 return NGX_ERROR;
445 }
446 }
447 }
448
449 break;
450 }
451
452 return NGX_OK;
453 }
454
455
456 static ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle)
457 {
458 int tries, failed, reuseaddr, i;
459 ngx_err_t err;
460 ngx_log_t *log;
461 ngx_socket_t s;
462 ngx_listening_t *ls;
463
464 reuseaddr = 1;
465 #if (NGX_SUPPRESS_WARN)
466 failed = 0;
467 #endif
468
469 log = cycle->log;
470
471 /* TODO: tries configurable */
472
473 for (tries = 10; tries; tries--) {
474 failed = 0;
475
476 /* for each listening socket */
477
478 ls = cycle->listening.elts;
479 for (i = 0; i < cycle->listening.nelts; i++) {
480
481 if (ls[i].ignore) {
482 continue;
483 }
484
485 if (ls[i].fd != -1) {
486 continue;
487 }
488
489 if (ls[i].inherited) {
490
491 /* TODO: close on exit */
492 /* TODO: nonblocking */
493 /* TODO: deferred accept */
494
495 continue;
496 }
497
498 s = ngx_socket(ls[i].family, ls[i].type, ls[i].protocol,
499 ls[i].flags);
500
501 if (s == -1) {
502 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
503 ngx_socket_n " %s failed", ls[i].addr_text.data);
504 return NGX_ERROR;
505 }
506
507 #if (WIN32)
508 /*
509 * Winsock assignes a socket number divisible by 4
510 * so to find a connection we divide a socket number by 4.
511 */
512
513 if (s % 4) {
514 ngx_log_error(NGX_LOG_EMERG, ls->log, 0,
515 ngx_socket_n " created socket %d", s);
516 return NGX_ERROR;
517 }
518 #endif
519
520 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
521 (const void *) &reuseaddr, sizeof(int)) == -1) {
522 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
523 "setsockopt(SO_REUSEADDR) %s failed",
524 ls[i].addr_text.data);
525 return NGX_ERROR;
526 }
527
528 /* TODO: close on exit */
529
530 if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {
531 if (ngx_nonblocking(s) == -1) {
532 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
533 ngx_nonblocking_n " %s failed",
534 ls[i].addr_text.data);
535 return NGX_ERROR;
536 }
537 }
538
539 #if 0
540 if (ls[i].nonblocking) {
541 if (ngx_nonblocking(s) == -1) {
542 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
543 ngx_nonblocking_n " %s failed",
544 ls[i].addr_text.data);
545 return NGX_ERROR;
546 }
547 }
548 #endif
549
550 if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
551 err = ngx_socket_errno;
552 ngx_log_error(NGX_LOG_EMERG, log, err,
553 "bind() to %s failed", ls[i].addr_text.data);
554
555 if (err != NGX_EADDRINUSE)
556 return NGX_ERROR;
557
558 if (ngx_close_socket(s) == -1)
559 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
560 ngx_close_socket_n " %s failed",
561 ls[i].addr_text.data);
562
563 failed = 1;
564 continue;
565 }
566
567 if (listen(s, ls[i].backlog) == -1) {
568 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
569 "listen() to %s failed", ls[i].addr_text.data);
570 return NGX_ERROR;
571 }
572
573 /* TODO: deferred accept */
574
575 ls[i].fd = s;
576 }
577
578 if (!failed)
579 break;
580
581 /* TODO: delay configurable */
582
583 ngx_log_error(NGX_LOG_NOTICE, log, 0,
584 "try again to bind() after 500ms");
585 ngx_msleep(500);
586 }
587
588 if (failed) {
589 ngx_log_error(NGX_LOG_EMERG, log, 0, "still can not bind()");
590 return NGX_ERROR;
591 }
592
593 return NGX_OK;
594 }
595
596
597 #endif
598
599
600 void ngx_reopen_files(ngx_cycle_t *cycle)
601 {
602 ngx_fd_t fd;
603 ngx_int_t i;
604 ngx_open_file_t *file;
605
606 file = cycle->open_files.elts;
607 for (i = 0; i < cycle->open_files.nelts; i++) {
608 if (file[i].name.data == NULL) {
609 continue;
610 }
611
612 fd = ngx_open_file(file[i].name.data, NGX_FILE_RDWR,
613 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
614
615 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
616 "reopen file \"%s\", old:%d new:%d",
617 file[i].name.data, file[i].fd, fd);
618
619 if (fd == NGX_INVALID_FILE) {
620 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
621 ngx_open_file_n " \"%s\" failed", file[i].name.data);
622 continue;
623 }
624
625 #if (WIN32)
626 if (ngx_file_append_mode(fd) == NGX_ERROR) {
627 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
628 ngx_file_append_mode_n " \"%s\" failed",
629 file[i].name.data);
630
631 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
632 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
633 ngx_close_file_n " \"%s\" failed",
634 file[i].name.data);
635 }
636
637 continue;
638 }
639 #endif
640
641 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
642 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
643 ngx_close_file_n " \"%s\" failed",
644 file[i].name.data);
645 }
646
647 file[i].fd = fd;
648 }
649 }
650
651
652 #if 0
653
654 static void ngx_close_listening_sockets(ngx_cycle_t *cycle)
655 {
656 ngx_int_t i;
657 ngx_socket_t fd;
658 ngx_listening_t *ls;
659
660 if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
661 return;
662 }
663
664 ls = cycle->listening.elts;
665 for (i = 0; i < cycle->listening.nelts; i++) {
666 fd = ls[i].fd;
667
668 #if (WIN32)
669 /*
670 * Winsock assignes a socket number divisible by 4
671 * so to find a connection we divide a socket number by 4.
672 */
673
674 fd /= 4;
675 #endif
676
677 ngx_del_event(&cycle->read_events[fd], NGX_READ_EVENT, NGX_CLOSE_EVENT);
678
679 if (ngx_close_socket(ls[i].fd) == -1) {
680 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
681 ngx_close_socket_n " %s failed",
682 ls[i].addr_text.data);
683 }
684
685 cycle->connections[fd].fd = -1;
686 }
687 }
688
689 #endif
690
691
692 static void ngx_clean_old_cycles(ngx_event_t *ev)
693 {
694 int i, n, found, live;
695 ngx_log_t *log;
696 ngx_cycle_t **cycle;
697
698 log = ngx_cycle->log;
699 ngx_temp_pool->log = log;
700
701 ngx_log_debug(log, "clean old cycles");
702
703 live = 0;
704
705 cycle = ngx_old_cycles.elts;
706 for (i = 0; i < ngx_old_cycles.nelts; i++) {
707
708 if (cycle[i] == NULL) {
709 continue;
710 }
711
712 found = 0;
713
714 for (n = 0; n < cycle[i]->connection_n; n++) {
715 if (cycle[i]->connections[n].fd != -1) {
716 found = 1;
717 ngx_log_debug(log, "live fd: %d" _ n);
718 break;
719 }
720 }
721
722 if (found) {
723 live = 1;
724 continue;
725 }
726
727 ngx_log_debug(log, "clean old cycle: %d" _ i);
728 ngx_destroy_pool(cycle[i]->pool);
729 cycle[i] = NULL;
730 }
731
732 ngx_log_debug(log, "old cycles status: %d" _ live);
733
734 if (live) {
735 ngx_log_debug(log, "TIMER");
736 ngx_add_timer(ev, 30000);
737
738 } else {
739 ngx_destroy_pool(ngx_temp_pool);
740 ngx_temp_pool = NULL;
741 ngx_old_cycles.nelts = 0;
742 }
743 }