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