~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/core/ngx_cycle.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

  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->