Annotation of embedaddon/nginx/src/core/ngx_cycle.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10: #include <ngx_event.h>
11:
12:
13: static void ngx_destroy_cycle_pools(ngx_conf_t *conf);
14: static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2);
15: static ngx_int_t ngx_init_zone_pool(ngx_cycle_t *cycle,
16: ngx_shm_zone_t *shm_zone);
17: static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log);
18: static void ngx_clean_old_cycles(ngx_event_t *ev);
19:
20:
21: volatile ngx_cycle_t *ngx_cycle;
22: ngx_array_t ngx_old_cycles;
23:
24: static ngx_pool_t *ngx_temp_pool;
25: static ngx_event_t ngx_cleaner_event;
26:
27: ngx_uint_t ngx_test_config;
28: ngx_uint_t ngx_quiet_mode;
29:
30: #if (NGX_THREADS)
31: ngx_tls_key_t ngx_core_tls_key;
32: #endif
33:
34:
35: /* STUB NAME */
36: static ngx_connection_t dumb;
37: /* STUB */
38:
39: static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH);
40:
41:
42: ngx_cycle_t *
43: ngx_init_cycle(ngx_cycle_t *old_cycle)
44: {
45: void *rv;
46: char **senv, **env;
47: ngx_uint_t i, n;
48: ngx_log_t *log;
49: ngx_time_t *tp;
50: ngx_conf_t conf;
51: ngx_pool_t *pool;
52: ngx_cycle_t *cycle, **old;
53: ngx_shm_zone_t *shm_zone, *oshm_zone;
54: ngx_list_part_t *part, *opart;
55: ngx_open_file_t *file;
56: ngx_listening_t *ls, *nls;
57: ngx_core_conf_t *ccf, *old_ccf;
58: ngx_core_module_t *module;
59: char hostname[NGX_MAXHOSTNAMELEN];
60:
61: ngx_timezone_update();
62:
63: /* force localtime update with a new timezone */
64:
65: tp = ngx_timeofday();
66: tp->sec = 0;
67:
68: ngx_time_update();
69:
70:
71: log = old_cycle->log;
72:
73: pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
74: if (pool == NULL) {
75: return NULL;
76: }
77: pool->log = log;
78:
79: cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
80: if (cycle == NULL) {
81: ngx_destroy_pool(pool);
82: return NULL;
83: }
84:
85: cycle->pool = pool;
86: cycle->log = log;
87: cycle->new_log.log_level = NGX_LOG_ERR;
88: cycle->old_cycle = old_cycle;
89:
90: cycle->conf_prefix.len = old_cycle->conf_prefix.len;
91: cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix);
92: if (cycle->conf_prefix.data == NULL) {
93: ngx_destroy_pool(pool);
94: return NULL;
95: }
96:
97: cycle->prefix.len = old_cycle->prefix.len;
98: cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix);
99: if (cycle->prefix.data == NULL) {
100: ngx_destroy_pool(pool);
101: return NULL;
102: }
103:
104: cycle->conf_file.len = old_cycle->conf_file.len;
105: cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
106: if (cycle->conf_file.data == NULL) {
107: ngx_destroy_pool(pool);
108: return NULL;
109: }
110: ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data,
111: old_cycle->conf_file.len + 1);
112:
113: cycle->conf_param.len = old_cycle->conf_param.len;
114: cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param);
115: if (cycle->conf_param.data == NULL) {
116: ngx_destroy_pool(pool);
117: return NULL;
118: }
119:
120:
121: n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10;
122:
123: cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));
124: if (cycle->paths.elts == NULL) {
125: ngx_destroy_pool(pool);
126: return NULL;
127: }
128:
129: cycle->paths.nelts = 0;
130: cycle->paths.size = sizeof(ngx_path_t *);
131: cycle->paths.nalloc = n;
132: cycle->paths.pool = pool;
133:
134:
135: if (old_cycle->open_files.part.nelts) {
136: n = old_cycle->open_files.part.nelts;
137: for (part = old_cycle->open_files.part.next; part; part = part->next) {
138: n += part->nelts;
139: }
140:
141: } else {
142: n = 20;
143: }
144:
145: if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
146: != NGX_OK)
147: {
148: ngx_destroy_pool(pool);
149: return NULL;
150: }
151:
152:
153: if (old_cycle->shared_memory.part.nelts) {
154: n = old_cycle->shared_memory.part.nelts;
155: for (part = old_cycle->shared_memory.part.next; part; part = part->next)
156: {
157: n += part->nelts;
158: }
159:
160: } else {
161: n = 1;
162: }
163:
164: if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))
165: != NGX_OK)
166: {
167: ngx_destroy_pool(pool);
168: return NULL;
169: }
170:
171: n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
172:
173: cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
174: if (cycle->listening.elts == NULL) {
175: ngx_destroy_pool(pool);
176: return NULL;
177: }
178:
179: cycle->listening.nelts = 0;
180: cycle->listening.size = sizeof(ngx_listening_t);
181: cycle->listening.nalloc = n;
182: cycle->listening.pool = pool;
183:
184:
185: ngx_queue_init(&cycle->reusable_connections_queue);
186:
187:
188: cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
189: if (cycle->conf_ctx == NULL) {
190: ngx_destroy_pool(pool);
191: return NULL;
192: }
193:
194:
195: if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) {
196: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");
197: ngx_destroy_pool(pool);
198: return NULL;
199: }
200:
201: /* on Linux gethostname() silently truncates name that does not fit */
202:
203: hostname[NGX_MAXHOSTNAMELEN - 1] = '\0';
204: cycle->hostname.len = ngx_strlen(hostname);
205:
206: cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);
207: if (cycle->hostname.data == NULL) {
208: ngx_destroy_pool(pool);
209: return NULL;
210: }
211:
212: ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);
213:
214:
215: for (i = 0; ngx_modules[i]; i++) {
216: if (ngx_modules[i]->type != NGX_CORE_MODULE) {
217: continue;
218: }
219:
220: module = ngx_modules[i]->ctx;
221:
222: if (module->create_conf) {
223: rv = module->create_conf(cycle);
224: if (rv == NULL) {
225: ngx_destroy_pool(pool);
226: return NULL;
227: }
228: cycle->conf_ctx[ngx_modules[i]->index] = rv;
229: }
230: }
231:
232:
233: senv = environ;
234:
235:
236: ngx_memzero(&conf, sizeof(ngx_conf_t));
237: /* STUB: init array ? */
238: conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));
239: if (conf.args == NULL) {
240: ngx_destroy_pool(pool);
241: return NULL;
242: }
243:
244: conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
245: if (conf.temp_pool == NULL) {
246: ngx_destroy_pool(pool);
247: return NULL;
248: }
249:
250:
251: conf.ctx = cycle->conf_ctx;
252: conf.cycle = cycle;
253: conf.pool = pool;
254: conf.log = log;
255: conf.module_type = NGX_CORE_MODULE;
256: conf.cmd_type = NGX_MAIN_CONF;
257:
258: #if 0
259: log->log_level = NGX_LOG_DEBUG_ALL;
260: #endif
261:
262: if (ngx_conf_param(&conf) != NGX_CONF_OK) {
263: environ = senv;
264: ngx_destroy_cycle_pools(&conf);
265: return NULL;
266: }
267:
268: if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
269: environ = senv;
270: ngx_destroy_cycle_pools(&conf);
271: return NULL;
272: }
273:
274: if (ngx_test_config && !ngx_quiet_mode) {
275: ngx_log_stderr(0, "the configuration file %s syntax is ok",
276: cycle->conf_file.data);
277: }
278:
279: for (i = 0; ngx_modules[i]; i++) {
280: if (ngx_modules[i]->type != NGX_CORE_MODULE) {
281: continue;
282: }
283:
284: module = ngx_modules[i]->ctx;
285:
286: if (module->init_conf) {
287: if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
288: == NGX_CONF_ERROR)
289: {
290: environ = senv;
291: ngx_destroy_cycle_pools(&conf);
292: return NULL;
293: }
294: }
295: }
296:
297: if (ngx_process == NGX_PROCESS_SIGNALLER) {
298: return cycle;
299: }
300:
301: ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
302:
303: if (ngx_test_config) {
304:
305: if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) {
306: goto failed;
307: }
308:
309: } else if (!ngx_is_init_cycle(old_cycle)) {
310:
311: /*
312: * we do not create the pid file in the first ngx_init_cycle() call
313: * because we need to write the demonized process pid
314: */
315:
316: old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,
317: ngx_core_module);
318: if (ccf->pid.len != old_ccf->pid.len
319: || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0)
320: {
321: /* new pid file name */
322:
323: if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) {
324: goto failed;
325: }
326:
327: ngx_delete_pidfile(old_cycle);
328: }
329: }
330:
331:
332: if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) {
333: goto failed;
334: }
335:
336:
337: if (ngx_create_paths(cycle, ccf->user) != NGX_OK) {
338: goto failed;
339: }
340:
341:
342: if (cycle->new_log.file == NULL) {
343: cycle->new_log.file = ngx_conf_open_file(cycle, &error_log);
344: if (cycle->new_log.file == NULL) {
345: goto failed;
346: }
347: }
348:
349: /* open the new files */
350:
351: part = &cycle->open_files.part;
352: file = part->elts;
353:
354: for (i = 0; /* void */ ; i++) {
355:
356: if (i >= part->nelts) {
357: if (part->next == NULL) {
358: break;
359: }
360: part = part->next;
361: file = part->elts;
362: i = 0;
363: }
364:
365: if (file[i].name.len == 0) {
366: continue;
367: }
368:
369: file[i].fd = ngx_open_file(file[i].name.data,
370: NGX_FILE_APPEND,
371: NGX_FILE_CREATE_OR_OPEN,
372: NGX_FILE_DEFAULT_ACCESS);
373:
374: ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0,
375: "log: %p %d \"%s\"",
376: &file[i], file[i].fd, file[i].name.data);
377:
378: if (file[i].fd == NGX_INVALID_FILE) {
379: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
380: ngx_open_file_n " \"%s\" failed",
381: file[i].name.data);
382: goto failed;
383: }
384:
385: #if !(NGX_WIN32)
386: if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) {
387: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
388: "fcntl(FD_CLOEXEC) \"%s\" failed",
389: file[i].name.data);
390: goto failed;
391: }
392: #endif
393: }
394:
395: cycle->log = &cycle->new_log;
396: pool->log = &cycle->new_log;
397:
398:
399: /* create shared memory */
400:
401: part = &cycle->shared_memory.part;
402: shm_zone = part->elts;
403:
404: for (i = 0; /* void */ ; i++) {
405:
406: if (i >= part->nelts) {
407: if (part->next == NULL) {
408: break;
409: }
410: part = part->next;
411: shm_zone = part->elts;
412: i = 0;
413: }
414:
415: if (shm_zone[i].shm.size == 0) {
416: ngx_log_error(NGX_LOG_EMERG, log, 0,
417: "zero size shared memory zone \"%V\"",
418: &shm_zone[i].shm.name);
419: goto failed;
420: }
421:
422: shm_zone[i].shm.log = cycle->log;
423:
424: opart = &old_cycle->shared_memory.part;
425: oshm_zone = opart->elts;
426:
427: for (n = 0; /* void */ ; n++) {
428:
429: if (n >= opart->nelts) {
430: if (opart->next == NULL) {
431: break;
432: }
433: opart = opart->next;
434: oshm_zone = opart->elts;
435: n = 0;
436: }
437:
438: if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) {
439: continue;
440: }
441:
442: if (ngx_strncmp(shm_zone[i].shm.name.data,
443: oshm_zone[n].shm.name.data,
444: shm_zone[i].shm.name.len)
445: != 0)
446: {
447: continue;
448: }
449:
450: if (shm_zone[i].tag == oshm_zone[n].tag
451: && shm_zone[i].shm.size == oshm_zone[n].shm.size)
452: {
453: shm_zone[i].shm.addr = oshm_zone[n].shm.addr;
454:
455: if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data)
456: != NGX_OK)
457: {
458: goto failed;
459: }
460:
461: goto shm_zone_found;
462: }
463:
464: ngx_shm_free(&oshm_zone[n].shm);
465:
466: break;
467: }
468:
469: if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) {
470: goto failed;
471: }
472:
473: if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) {
474: goto failed;
475: }
476:
477: if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) {
478: goto failed;
479: }
480:
481: shm_zone_found:
482:
483: continue;
484: }
485:
486:
487: /* handle the listening sockets */
488:
489: if (old_cycle->listening.nelts) {
490: ls = old_cycle->listening.elts;
491: for (i = 0; i < old_cycle->listening.nelts; i++) {
492: ls[i].remain = 0;
493: }
494:
495: nls = cycle->listening.elts;
496: for (n = 0; n < cycle->listening.nelts; n++) {
497:
498: for (i = 0; i < old_cycle->listening.nelts; i++) {
499: if (ls[i].ignore) {
500: continue;
501: }
502:
503: if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK)
504: {
505: nls[n].fd = ls[i].fd;
506: nls[n].previous = &ls[i];
507: ls[i].remain = 1;
508:
509: if (ls[n].backlog != nls[i].backlog) {
510: nls[n].listen = 1;
511: }
512:
513: #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
514:
515: /*
516: * FreeBSD, except the most recent versions,
517: * could not remove accept filter
518: */
519: nls[n].deferred_accept = ls[i].deferred_accept;
520:
521: if (ls[i].accept_filter && nls[n].accept_filter) {
522: if (ngx_strcmp(ls[i].accept_filter,
523: nls[n].accept_filter)
524: != 0)
525: {
526: nls[n].delete_deferred = 1;
527: nls[n].add_deferred = 1;
528: }
529:
530: } else if (ls[i].accept_filter) {
531: nls[n].delete_deferred = 1;
532:
533: } else if (nls[n].accept_filter) {
534: nls[n].add_deferred = 1;
535: }
536: #endif
537:
538: #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
539:
540: if (ls[n].deferred_accept && !nls[n].deferred_accept) {
541: nls[n].delete_deferred = 1;
542:
543: } else if (ls[i].deferred_accept != nls[n].deferred_accept)
544: {
545: nls[n].add_deferred = 1;
546: }
547: #endif
548: break;
549: }
550: }
551:
552: if (nls[n].fd == -1) {
553: nls[n].open = 1;
554: }
555: }
556:
557: } else {
558: ls = cycle->listening.elts;
559: for (i = 0; i < cycle->listening.nelts; i++) {
560: ls[i].open = 1;
561: #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
562: if (ls[i].accept_filter) {
563: ls[i].add_deferred = 1;
564: }
565: #endif
566: #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
567: if (ls[i].deferred_accept) {
568: ls[i].add_deferred = 1;
569: }
570: #endif
571: }
572: }
573:
574: if (ngx_open_listening_sockets(cycle) != NGX_OK) {
575: goto failed;
576: }
577:
578: if (!ngx_test_config) {
579: ngx_configure_listening_sockets(cycle);
580: }
581:
582:
583: /* commit the new cycle configuration */
584:
585: if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) {
586:
587: if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
588: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
589: ngx_set_stderr_n " failed");
590: }
591: }
592:
593: pool->log = cycle->log;
594:
595: for (i = 0; ngx_modules[i]; i++) {
596: if (ngx_modules[i]->init_module) {
597: if (ngx_modules[i]->init_module(cycle) != NGX_OK) {
598: /* fatal */
599: exit(1);
600: }
601: }
602: }
603:
604:
605: /* close and delete stuff that lefts from an old cycle */
606:
607: /* free the unnecessary shared memory */
608:
609: opart = &old_cycle->shared_memory.part;
610: oshm_zone = opart->elts;
611:
612: for (i = 0; /* void */ ; i++) {
613:
614: if (i >= opart->nelts) {
615: if (opart->next == NULL) {
616: goto old_shm_zone_done;
617: }
618: opart = opart->next;
619: oshm_zone = opart->elts;
620: i = 0;
621: }
622:
623: part = &cycle->shared_memory.part;
624: shm_zone = part->elts;
625:
626: for (n = 0; /* void */ ; n++) {
627:
628: if (n >= part->nelts) {
629: if (part->next == NULL) {
630: break;
631: }
632: part = part->next;
633: shm_zone = part->elts;
634: n = 0;
635: }
636:
637: if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len
638: && ngx_strncmp(oshm_zone[i].shm.name.data,
639: shm_zone[n].shm.name.data,
640: oshm_zone[i].shm.name.len)
641: == 0)
642: {
643: goto live_shm_zone;
644: }
645: }
646:
647: ngx_shm_free(&oshm_zone[i].shm);
648:
649: live_shm_zone:
650:
651: continue;
652: }
653:
654: old_shm_zone_done:
655:
656:
657: /* close the unnecessary listening sockets */
658:
659: ls = old_cycle->listening.elts;
660: for (i = 0; i < old_cycle->listening.nelts; i++) {
661:
662: if (ls[i].remain || ls[i].fd == -1) {
663: continue;
664: }
665:
666: if (ngx_close_socket(ls[i].fd) == -1) {
667: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
668: ngx_close_socket_n " listening socket on %V failed",
669: &ls[i].addr_text);
670: }
671:
672: #if (NGX_HAVE_UNIX_DOMAIN)
673:
674: if (ls[i].sockaddr->sa_family == AF_UNIX) {
675: u_char *name;
676:
677: name = ls[i].addr_text.data + sizeof("unix:") - 1;
678:
679: ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
680: "deleting socket %s", name);
681:
682: if (ngx_delete_file(name) == NGX_FILE_ERROR) {
683: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
684: ngx_delete_file_n " %s failed", name);
685: }
686: }
687:
688: #endif
689: }
690:
691:
692: /* close the unnecessary open files */
693:
694: part = &old_cycle->open_files.part;
695: file = part->elts;
696:
697: for (i = 0; /* void */ ; i++) {
698:
699: if (i >= part->nelts) {
700: if (part->next == NULL) {
701: break;
702: }
703: part = part->next;
704: file = part->elts;
705: i = 0;
706: }
707:
708: if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) {
709: continue;
710: }
711:
712: if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
713: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
714: ngx_close_file_n " \"%s\" failed",
715: file[i].name.data);
716: }
717: }
718:
719: ngx_destroy_pool(conf.temp_pool);
720:
721: if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) {
722:
723: /*
724: * perl_destruct() frees environ, if it is not the same as it was at
725: * perl_construct() time, therefore we save the previous cycle
726: * environment before ngx_conf_parse() where it will be changed.
727: */
728:
729: env = environ;
730: environ = senv;
731:
732: ngx_destroy_pool(old_cycle->pool);
733: cycle->old_cycle = NULL;
734:
735: environ = env;
736:
737: return cycle;
738: }
739:
740:
741: if (ngx_temp_pool == NULL) {
742: ngx_temp_pool = ngx_create_pool(128, cycle->log);
743: if (ngx_temp_pool == NULL) {
744: ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
745: "could not create ngx_temp_pool");
746: exit(1);
747: }
748:
749: n = 10;
750: ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool,
751: n * sizeof(ngx_cycle_t *));
752: if (ngx_old_cycles.elts == NULL) {
753: exit(1);
754: }
755: ngx_old_cycles.nelts = 0;
756: ngx_old_cycles.size = sizeof(ngx_cycle_t *);
757: ngx_old_cycles.nalloc = n;
758: ngx_old_cycles.pool = ngx_temp_pool;
759:
760: ngx_cleaner_event.handler = ngx_clean_old_cycles;
761: ngx_cleaner_event.log = cycle->log;
762: ngx_cleaner_event.data = &dumb;
763: dumb.fd = (ngx_socket_t) -1;
764: }
765:
766: ngx_temp_pool->log = cycle->log;
767:
768: old = ngx_array_push(&ngx_old_cycles);
769: if (old == NULL) {
770: exit(1);
771: }
772: *old = old_cycle;
773:
774: if (!ngx_cleaner_event.timer_set) {
775: ngx_add_timer(&ngx_cleaner_event, 30000);
776: ngx_cleaner_event.timer_set = 1;
777: }
778:
779: return cycle;
780:
781:
782: failed:
783:
784: if (!ngx_is_init_cycle(old_cycle)) {
785: old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,
786: ngx_core_module);
787: if (old_ccf->environment) {
788: environ = old_ccf->environment;
789: }
790: }
791:
792: /* rollback the new cycle configuration */
793:
794: part = &cycle->open_files.part;
795: file = part->elts;
796:
797: for (i = 0; /* void */ ; i++) {
798:
799: if (i >= part->nelts) {
800: if (part->next == NULL) {
801: break;
802: }
803: part = part->next;
804: file = part->elts;
805: i = 0;
806: }
807:
808: if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) {
809: continue;
810: }
811:
812: if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
813: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
814: ngx_close_file_n " \"%s\" failed",
815: file[i].name.data);
816: }
817: }
818:
819: if (ngx_test_config) {
820: ngx_destroy_cycle_pools(&conf);
821: return NULL;
822: }
823:
824: ls = cycle->listening.elts;
825: for (i = 0; i < cycle->listening.nelts; i++) {
826: if (ls[i].fd == -1 || !ls[i].open) {
827: continue;
828: }
829:
830: if (ngx_close_socket(ls[i].fd) == -1) {
831: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
832: ngx_close_socket_n " %V failed",
833: &ls[i].addr_text);
834: }
835: }
836:
837: ngx_destroy_cycle_pools(&conf);
838:
839: return NULL;
840: }
841:
842:
843: static void
844: ngx_destroy_cycle_pools(ngx_conf_t *conf)
845: {
846: ngx_destroy_pool(conf->temp_pool);
847: ngx_destroy_pool(conf->pool);
848: }
849:
850:
851: static ngx_int_t
852: ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2)
853: {
854: struct sockaddr_in *sin1, *sin2;
855: #if (NGX_HAVE_INET6)
856: struct sockaddr_in6 *sin61, *sin62;
857: #endif
858: #if (NGX_HAVE_UNIX_DOMAIN)
859: struct sockaddr_un *saun1, *saun2;
860: #endif
861:
862: if (sa1->sa_family != sa2->sa_family) {
863: return NGX_DECLINED;
864: }
865:
866: switch (sa1->sa_family) {
867:
868: #if (NGX_HAVE_INET6)
869: case AF_INET6:
870: sin61 = (struct sockaddr_in6 *) sa1;
871: sin62 = (struct sockaddr_in6 *) sa2;
872:
873: if (sin61->sin6_port != sin62->sin6_port) {
874: return NGX_DECLINED;
875: }
876:
877: if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
878: return NGX_DECLINED;
879: }
880:
881: break;
882: #endif
883:
884: #if (NGX_HAVE_UNIX_DOMAIN)
885: case AF_UNIX:
886: saun1 = (struct sockaddr_un *) sa1;
887: saun2 = (struct sockaddr_un *) sa2;
888:
889: if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path,
890: sizeof(saun1->sun_path))
891: != 0)
892: {
893: return NGX_DECLINED;
894: }
895:
896: break;
897: #endif
898:
899: default: /* AF_INET */
900:
901: sin1 = (struct sockaddr_in *) sa1;
902: sin2 = (struct sockaddr_in *) sa2;
903:
904: if (sin1->sin_port != sin2->sin_port) {
905: return NGX_DECLINED;
906: }
907:
908: if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
909: return NGX_DECLINED;
910: }
911:
912: break;
913: }
914:
915: return NGX_OK;
916: }
917:
918:
919: static ngx_int_t
920: ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *zn)
921: {
922: u_char *file;
923: ngx_slab_pool_t *sp;
924:
925: sp = (ngx_slab_pool_t *) zn->shm.addr;
926:
927: if (zn->shm.exists) {
928:
929: if (sp == sp->addr) {
930: return NGX_OK;
931: }
932:
933: ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
934: "shared zone \"%V\" has no equal addresses: %p vs %p",
935: &zn->shm.name, sp->addr, sp);
936: return NGX_ERROR;
937: }
938:
939: sp->end = zn->shm.addr + zn->shm.size;
940: sp->min_shift = 3;
941: sp->addr = zn->shm.addr;
942:
943: #if (NGX_HAVE_ATOMIC_OPS)
944:
945: file = NULL;
946:
947: #else
948:
949: file = ngx_pnalloc(cycle->pool, cycle->lock_file.len + zn->shm.name.len);
950: if (file == NULL) {
951: return NGX_ERROR;
952: }
953:
954: (void) ngx_sprintf(file, "%V%V%Z", &cycle->lock_file, &zn->shm.name);
955:
956: #endif
957:
958: if (ngx_shmtx_create(&sp->mutex, &sp->lock, file) != NGX_OK) {
959: return NGX_ERROR;
960: }
961:
962: ngx_slab_init(sp);
963:
964: return NGX_OK;
965: }
966:
967:
968: ngx_int_t
969: ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
970: {
971: size_t len;
972: ngx_uint_t create;
973: ngx_file_t file;
974: u_char pid[NGX_INT64_LEN + 2];
975:
976: if (ngx_process > NGX_PROCESS_MASTER) {
977: return NGX_OK;
978: }
979:
980: ngx_memzero(&file, sizeof(ngx_file_t));
981:
982: file.name = *name;
983: file.log = log;
984:
985: create = ngx_test_config ? NGX_FILE_CREATE_OR_OPEN : NGX_FILE_TRUNCATE;
986:
987: file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR,
988: create, NGX_FILE_DEFAULT_ACCESS);
989:
990: if (file.fd == NGX_INVALID_FILE) {
991: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
992: ngx_open_file_n " \"%s\" failed", file.name.data);
993: return NGX_ERROR;
994: }
995:
996: if (!ngx_test_config) {
997: len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;
998:
999: if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
1000: return NGX_ERROR;
1001: }
1002: }
1003:
1004: if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
1005: ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
1006: ngx_close_file_n " \"%s\" failed", file.name.data);
1007: }
1008:
1009: return NGX_OK;
1010: }
1011:
1012:
1013: void
1014: ngx_delete_pidfile(ngx_cycle_t *cycle)
1015: {
1016: u_char *name;
1017: ngx_core_conf_t *ccf;
1018:
1019: ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
1020:
1021: name = ngx_new_binary ? ccf->oldpid.data : ccf->pid.data;
1022:
1023: if (ngx_delete_file(name) == NGX_FILE_ERROR) {
1024: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1025: ngx_delete_file_n " \"%s\" failed", name);
1026: }
1027: }
1028:
1029:
1030: ngx_int_t
1031: ngx_signal_process(ngx_cycle_t *cycle, char *sig)
1032: {
1033: ssize_t n;
1034: ngx_int_t pid;
1035: ngx_file_t file;
1036: ngx_core_conf_t *ccf;
1037: u_char buf[NGX_INT64_LEN + 2];
1038:
1039: ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started");
1040:
1041: ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
1042:
1043: ngx_memzero(&file, sizeof(ngx_file_t));
1044:
1045: file.name = ccf->pid;
1046: file.log = cycle->log;
1047:
1048: file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY,
1049: NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS);
1050:
1051: if (file.fd == NGX_INVALID_FILE) {
1052: ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
1053: ngx_open_file_n " \"%s\" failed", file.name.data);
1054: return 1;
1055: }
1056:
1057: n = ngx_read_file(&file, buf, NGX_INT64_LEN + 2, 0);
1058:
1059: if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
1060: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1061: ngx_close_file_n " \"%s\" failed", file.name.data);
1062: }
1063:
1064: if (n == NGX_ERROR) {
1065: return 1;
1066: }
1067:
1068: while (n-- && (buf[n] == CR || buf[n] == LF)) { /* void */ }
1069:
1070: pid = ngx_atoi(buf, ++n);
1071:
1072: if (pid == NGX_ERROR) {
1073: ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
1074: "invalid PID number \"%*s\" in \"%s\"",
1075: n, buf, file.name.data);
1076: return 1;
1077: }
1078:
1079: return ngx_os_signal_process(cycle, sig, pid);
1080:
1081: }
1082:
1083:
1084: static ngx_int_t
1085: ngx_test_lockfile(u_char *file, ngx_log_t *log)
1086: {
1087: #if !(NGX_HAVE_ATOMIC_OPS)
1088: ngx_fd_t fd;
1089:
1090: fd = ngx_open_file(file, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN,
1091: NGX_FILE_DEFAULT_ACCESS);
1092:
1093: if (fd == NGX_INVALID_FILE) {
1094: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
1095: ngx_open_file_n " \"%s\" failed", file);
1096: return NGX_ERROR;
1097: }
1098:
1099: if (ngx_close_file(fd) == NGX_FILE_ERROR) {
1100: ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
1101: ngx_close_file_n " \"%s\" failed", file);
1102: }
1103:
1104: if (ngx_delete_file(file) == NGX_FILE_ERROR) {
1105: ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
1106: ngx_delete_file_n " \"%s\" failed", file);
1107: }
1108:
1109: #endif
1110:
1111: return NGX_OK;
1112: }
1113:
1114:
1115: void
1116: ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
1117: {
1118: ngx_fd_t fd;
1119: ngx_uint_t i;
1120: ngx_list_part_t *part;
1121: ngx_open_file_t *file;
1122:
1123: part = &cycle->open_files.part;
1124: file = part->elts;
1125:
1126: for (i = 0; /* void */ ; i++) {
1127:
1128: if (i >= part->nelts) {
1129: if (part->next == NULL) {
1130: break;
1131: }
1132: part = part->next;
1133: file = part->elts;
1134: i = 0;
1135: }
1136:
1137: if (file[i].name.len == 0) {
1138: continue;
1139: }
1140:
1141: if (file[i].flush) {
1142: file[i].flush(&file[i], cycle->log);
1143: }
1144:
1145: fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND,
1146: NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS);
1147:
1148: ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
1149: "reopen file \"%s\", old:%d new:%d",
1150: file[i].name.data, file[i].fd, fd);
1151:
1152: if (fd == NGX_INVALID_FILE) {
1153: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1154: ngx_open_file_n " \"%s\" failed", file[i].name.data);
1155: continue;
1156: }
1157:
1158: #if !(NGX_WIN32)
1159: if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) {
1160: ngx_file_info_t fi;
1161:
1162: if (ngx_file_info((const char *) file[i].name.data, &fi)
1163: == NGX_FILE_ERROR)
1164: {
1165: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1166: ngx_file_info_n " \"%s\" failed",
1167: file[i].name.data);
1168:
1169: if (ngx_close_file(fd) == NGX_FILE_ERROR) {
1170: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1171: ngx_close_file_n " \"%s\" failed",
1172: file[i].name.data);
1173: }
1174: }
1175:
1176: if (fi.st_uid != user) {
1177: if (chown((const char *) file[i].name.data, user, -1) == -1) {
1178: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1179: "chown(\"%s\", %d) failed",
1180: file[i].name.data, user);
1181:
1182: if (ngx_close_file(fd) == NGX_FILE_ERROR) {
1183: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1184: ngx_close_file_n " \"%s\" failed",
1185: file[i].name.data);
1186: }
1187: }
1188: }
1189:
1190: if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) {
1191:
1192: fi.st_mode |= (S_IRUSR|S_IWUSR);
1193:
1194: if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) {
1195: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1196: "chmod() \"%s\" failed", file[i].name.data);
1197:
1198: if (ngx_close_file(fd) == NGX_FILE_ERROR) {
1199: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1200: ngx_close_file_n " \"%s\" failed",
1201: file[i].name.data);
1202: }
1203: }
1204: }
1205: }
1206:
1207: if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
1208: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1209: "fcntl(FD_CLOEXEC) \"%s\" failed",
1210: file[i].name.data);
1211:
1212: if (ngx_close_file(fd) == NGX_FILE_ERROR) {
1213: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1214: ngx_close_file_n " \"%s\" failed",
1215: file[i].name.data);
1216: }
1217:
1218: continue;
1219: }
1220: #endif
1221:
1222: if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
1223: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1224: ngx_close_file_n " \"%s\" failed",
1225: file[i].name.data);
1226: }
1227:
1228: file[i].fd = fd;
1229: }
1230:
1231: #if !(NGX_WIN32)
1232:
1233: if (cycle->log->file->fd != STDERR_FILENO) {
1234: if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {
1235: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1236: "dup2(STDERR) failed");
1237: }
1238: }
1239:
1240: #endif
1241: }
1242:
1243:
1244: ngx_shm_zone_t *
1245: ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)
1246: {
1247: ngx_uint_t i;
1248: ngx_shm_zone_t *shm_zone;
1249: ngx_list_part_t *part;
1250:
1251: part = &cf->cycle->shared_memory.part;
1252: shm_zone = part->elts;
1253:
1254: for (i = 0; /* void */ ; i++) {
1255:
1256: if (i >= part->nelts) {
1257: if (part->next == NULL) {
1258: break;
1259: }
1260: part = part->next;
1261: shm_zone = part->elts;
1262: i = 0;
1263: }
1264:
1265: if (name->len != shm_zone[i].shm.name.len) {
1266: continue;
1267: }
1268:
1269: if (ngx_strncmp(name->data, shm_zone[i].shm.name.data, name->len)
1270: != 0)
1271: {
1272: continue;
1273: }
1274:
1275: if (tag != shm_zone[i].tag) {
1276: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1277: "the shared memory zone \"%V\" is "
1278: "already declared for a different use",
1279: &shm_zone[i].shm.name);
1280: return NULL;
1281: }
1282:
1283: if (size && size != shm_zone[i].shm.size) {
1284: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1285: "the size %uz of shared memory zone \"%V\" "
1286: "conflicts with already declared size %uz",
1287: size, &shm_zone[i].shm.name, shm_zone[i].shm.size);
1288: return NULL;
1289: }
1290:
1291: return &shm_zone[i];
1292: }
1293:
1294: shm_zone = ngx_list_push(&cf->cycle->shared_memory);
1295:
1296: if (shm_zone == NULL) {
1297: return NULL;
1298: }
1299:
1300: shm_zone->data = NULL;
1301: shm_zone->shm.log = cf->cycle->log;
1302: shm_zone->shm.size = size;
1303: shm_zone->shm.name = *name;
1304: shm_zone->shm.exists = 0;
1305: shm_zone->init = NULL;
1306: shm_zone->tag = tag;
1307:
1308: return shm_zone;
1309: }
1310:
1311:
1312: static void
1313: ngx_clean_old_cycles(ngx_event_t *ev)
1314: {
1315: ngx_uint_t i, n, found, live;
1316: ngx_log_t *log;
1317: ngx_cycle_t **cycle;
1318:
1319: log = ngx_cycle->log;
1320: ngx_temp_pool->log = log;
1321:
1322: ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "clean old cycles");
1323:
1324: live = 0;
1325:
1326: cycle = ngx_old_cycles.elts;
1327: for (i = 0; i < ngx_old_cycles.nelts; i++) {
1328:
1329: if (cycle[i] == NULL) {
1330: continue;
1331: }
1332:
1333: found = 0;
1334:
1335: for (n = 0; n < cycle[i]->connection_n; n++) {
1336: if (cycle[i]->connections[n].fd != (ngx_socket_t) -1) {
1337: found = 1;
1338:
1339: ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "live fd:%d", n);
1340:
1341: break;
1342: }
1343: }
1344:
1345: if (found) {
1346: live = 1;
1347: continue;
1348: }
1349:
1350: ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "clean old cycle: %d", i);
1351:
1352: ngx_destroy_pool(cycle[i]->pool);
1353: cycle[i] = NULL;
1354: }
1355:
1356: ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "old cycles status: %d", live);
1357:
1358: if (live) {
1359: ngx_add_timer(ev, 30000);
1360:
1361: } else {
1362: ngx_destroy_pool(ngx_temp_pool);
1363: ngx_temp_pool = NULL;
1364: ngx_old_cycles.nelts = 0;
1365: }
1366: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>