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