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