xref: /f-stack/app/nginx-1.16.1/src/event/ngx_event.c (revision 10c1fea8)
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 #define DEFAULT_CONNECTIONS  512
14 
15 
16 extern ngx_module_t ngx_kqueue_module;
17 extern ngx_module_t ngx_eventport_module;
18 extern ngx_module_t ngx_devpoll_module;
19 extern ngx_module_t ngx_epoll_module;
20 extern ngx_module_t ngx_select_module;
21 
22 
23 static char *ngx_event_init_conf(ngx_cycle_t *cycle, void *conf);
24 static ngx_int_t ngx_event_module_init(ngx_cycle_t *cycle);
25 static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle);
26 static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
27 
28 static char *ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd,
29     void *conf);
30 static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
31 static char *ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd,
32     void *conf);
33 
34 static void *ngx_event_core_create_conf(ngx_cycle_t *cycle);
35 static char *ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf);
36 
37 #if (NGX_HAVE_FSTACK)
38 extern ngx_int_t ngx_ff_epoll_process_events(ngx_cycle_t *cycle,
39     ngx_msec_t timer, ngx_uint_t flags);
40 #endif
41 
42 static ngx_uint_t     ngx_timer_resolution;
43 sig_atomic_t          ngx_event_timer_alarm;
44 
45 static ngx_uint_t     ngx_event_max_module;
46 
47 ngx_uint_t            ngx_event_flags;
48 ngx_event_actions_t   ngx_event_actions;
49 
50 
51 static ngx_atomic_t   connection_counter = 1;
52 ngx_atomic_t         *ngx_connection_counter = &connection_counter;
53 
54 
55 ngx_atomic_t         *ngx_accept_mutex_ptr;
56 ngx_shmtx_t           ngx_accept_mutex;
57 ngx_uint_t            ngx_use_accept_mutex;
58 ngx_uint_t            ngx_accept_events;
59 ngx_uint_t            ngx_accept_mutex_held;
60 ngx_msec_t            ngx_accept_mutex_delay;
61 ngx_int_t             ngx_accept_disabled;
62 
63 #if (NGX_HAVE_FSTACK)
64 static ngx_msec_t     ngx_schedule_timeout;
65 #endif
66 
67 #if (NGX_STAT_STUB)
68 
69 static ngx_atomic_t   ngx_stat_accepted0;
70 ngx_atomic_t         *ngx_stat_accepted = &ngx_stat_accepted0;
71 static ngx_atomic_t   ngx_stat_handled0;
72 ngx_atomic_t         *ngx_stat_handled = &ngx_stat_handled0;
73 static ngx_atomic_t   ngx_stat_requests0;
74 ngx_atomic_t         *ngx_stat_requests = &ngx_stat_requests0;
75 static ngx_atomic_t   ngx_stat_active0;
76 ngx_atomic_t         *ngx_stat_active = &ngx_stat_active0;
77 static ngx_atomic_t   ngx_stat_reading0;
78 ngx_atomic_t         *ngx_stat_reading = &ngx_stat_reading0;
79 static ngx_atomic_t   ngx_stat_writing0;
80 ngx_atomic_t         *ngx_stat_writing = &ngx_stat_writing0;
81 static ngx_atomic_t   ngx_stat_waiting0;
82 ngx_atomic_t         *ngx_stat_waiting = &ngx_stat_waiting0;
83 
84 #endif
85 
86 
87 
88 static ngx_command_t  ngx_events_commands[] = {
89 
90     { ngx_string("events"),
91       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
92       ngx_events_block,
93       0,
94       0,
95       NULL },
96 
97       ngx_null_command
98 };
99 
100 
101 static ngx_core_module_t  ngx_events_module_ctx = {
102     ngx_string("events"),
103     NULL,
104     ngx_event_init_conf
105 };
106 
107 
108 ngx_module_t  ngx_events_module = {
109     NGX_MODULE_V1,
110     &ngx_events_module_ctx,                /* module context */
111     ngx_events_commands,                   /* module directives */
112     NGX_CORE_MODULE,                       /* module type */
113     NULL,                                  /* init master */
114     NULL,                                  /* init module */
115     NULL,                                  /* init process */
116     NULL,                                  /* init thread */
117     NULL,                                  /* exit thread */
118     NULL,                                  /* exit process */
119     NULL,                                  /* exit master */
120     NGX_MODULE_V1_PADDING
121 };
122 
123 
124 static ngx_str_t  event_core_name = ngx_string("event_core");
125 
126 
127 static ngx_command_t  ngx_event_core_commands[] = {
128 
129     { ngx_string("worker_connections"),
130       NGX_EVENT_CONF|NGX_CONF_TAKE1,
131       ngx_event_connections,
132       0,
133       0,
134       NULL },
135 
136     { ngx_string("use"),
137       NGX_EVENT_CONF|NGX_CONF_TAKE1,
138       ngx_event_use,
139       0,
140       0,
141       NULL },
142 
143     { ngx_string("multi_accept"),
144       NGX_EVENT_CONF|NGX_CONF_FLAG,
145       ngx_conf_set_flag_slot,
146       0,
147       offsetof(ngx_event_conf_t, multi_accept),
148       NULL },
149 
150     { ngx_string("accept_mutex"),
151       NGX_EVENT_CONF|NGX_CONF_FLAG,
152       ngx_conf_set_flag_slot,
153       0,
154       offsetof(ngx_event_conf_t, accept_mutex),
155       NULL },
156 
157     { ngx_string("accept_mutex_delay"),
158       NGX_EVENT_CONF|NGX_CONF_TAKE1,
159       ngx_conf_set_msec_slot,
160       0,
161       offsetof(ngx_event_conf_t, accept_mutex_delay),
162       NULL },
163 
164     { ngx_string("debug_connection"),
165       NGX_EVENT_CONF|NGX_CONF_TAKE1,
166       ngx_event_debug_connection,
167       0,
168       0,
169       NULL },
170 
171       ngx_null_command
172 };
173 
174 
175 static ngx_event_module_t  ngx_event_core_module_ctx = {
176     &event_core_name,
177     ngx_event_core_create_conf,            /* create configuration */
178     ngx_event_core_init_conf,              /* init configuration */
179 
180     { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
181 };
182 
183 
184 ngx_module_t  ngx_event_core_module = {
185     NGX_MODULE_V1,
186     &ngx_event_core_module_ctx,            /* module context */
187     ngx_event_core_commands,               /* module directives */
188     NGX_EVENT_MODULE,                      /* module type */
189     NULL,                                  /* init master */
190     ngx_event_module_init,                 /* init module */
191     ngx_event_process_init,                /* init process */
192     NULL,                                  /* init thread */
193     NULL,                                  /* exit thread */
194     NULL,                                  /* exit process */
195     NULL,                                  /* exit master */
196     NGX_MODULE_V1_PADDING
197 };
198 
199 
200 void
ngx_process_events_and_timers(ngx_cycle_t * cycle)201 ngx_process_events_and_timers(ngx_cycle_t *cycle)
202 {
203     ngx_uint_t  flags;
204     ngx_msec_t  timer, delta;
205 #if (NGX_HAVE_FSTACK)
206     static ngx_msec_t initial; //msec
207 #endif
208 
209     if (ngx_timer_resolution) {
210         timer = NGX_TIMER_INFINITE;
211         flags = 0;
212 
213     } else {
214         timer = ngx_event_find_timer();
215         flags = NGX_UPDATE_TIME;
216 
217 #if (NGX_WIN32)
218 
219         /* handle signals from master in case of network inactivity */
220 
221         if (timer == NGX_TIMER_INFINITE || timer > 500) {
222             timer = 500;
223         }
224 
225 #endif
226     }
227 
228     if (ngx_use_accept_mutex) {
229         if (ngx_accept_disabled > 0) {
230             ngx_accept_disabled--;
231 
232         } else {
233             if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
234                 return;
235             }
236 
237             if (ngx_accept_mutex_held) {
238                 flags |= NGX_POST_EVENTS;
239 
240             } else {
241                 if (timer == NGX_TIMER_INFINITE
242                     || timer > ngx_accept_mutex_delay)
243                 {
244                     timer = ngx_accept_mutex_delay;
245                 }
246             }
247         }
248     }
249 
250     delta = ngx_current_msec;
251 
252 #if (NGX_HAVE_FSTACK)
253     /*
254      * NGX_FF_PROCESS_*s run on both fstack and kernel,
255      * others ( e.g. cache manager/loader ) only run on kernel.
256      */
257     if(!!ngx_ff_process) {
258         (void) ngx_process_events(cycle, timer, flags);
259 
260         /*
261          * handle message from kernel ( e.g. signals)
262          * in case of network inactivity
263          */
264         if (ngx_current_msec - initial >= ngx_schedule_timeout) {
265             (void) ngx_ff_process_host_events(cycle, 0, flags);
266 
267             /* Update timer*/
268             initial = ngx_current_msec;
269         }
270     } else {
271         (void) ngx_ff_process_host_events(cycle, timer, flags);
272     }
273 
274     delta = ngx_current_msec - delta;
275 #else
276     (void) ngx_process_events(cycle, timer, flags);
277 
278     delta = ngx_current_msec - delta;
279 
280     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
281                    "timer delta: %M", delta);
282 
283     ngx_event_process_posted(cycle, &ngx_posted_accept_events);
284 #endif
285     if (ngx_accept_mutex_held) {
286         ngx_shmtx_unlock(&ngx_accept_mutex);
287     }
288 
289     if (delta) {
290         ngx_event_expire_timers();
291     }
292 
293     ngx_event_process_posted(cycle, &ngx_posted_events);
294 }
295 
296 
297 ngx_int_t
ngx_handle_read_event(ngx_event_t * rev,ngx_uint_t flags)298 ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)
299 {
300     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
301 
302         /* kqueue, epoll */
303 
304         if (!rev->active && !rev->ready) {
305             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT)
306                 == NGX_ERROR)
307             {
308                 return NGX_ERROR;
309             }
310         }
311 
312         return NGX_OK;
313 
314     } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
315 
316         /* select, poll, /dev/poll */
317 
318         if (!rev->active && !rev->ready) {
319             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
320                 == NGX_ERROR)
321             {
322                 return NGX_ERROR;
323             }
324 
325             return NGX_OK;
326         }
327 
328         if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) {
329             if (ngx_del_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT | flags)
330                 == NGX_ERROR)
331             {
332                 return NGX_ERROR;
333             }
334 
335             return NGX_OK;
336         }
337 
338     } else if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
339 
340         /* event ports */
341 
342         if (!rev->active && !rev->ready) {
343             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
344                 return NGX_ERROR;
345             }
346 
347             return NGX_OK;
348         }
349 
350         if (rev->oneshot && !rev->ready) {
351             if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
352                 return NGX_ERROR;
353             }
354 
355             return NGX_OK;
356         }
357     }
358 
359     /* iocp */
360 
361     return NGX_OK;
362 }
363 
364 
365 ngx_int_t
ngx_handle_write_event(ngx_event_t * wev,size_t lowat)366 ngx_handle_write_event(ngx_event_t *wev, size_t lowat)
367 {
368     ngx_connection_t  *c;
369 
370     if (lowat) {
371         c = wev->data;
372 
373         if (ngx_send_lowat(c, lowat) == NGX_ERROR) {
374             return NGX_ERROR;
375         }
376     }
377 
378     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
379 
380         /* kqueue, epoll */
381 
382         if (!wev->active && !wev->ready) {
383             if (ngx_add_event(wev, NGX_WRITE_EVENT,
384                               NGX_CLEAR_EVENT | (lowat ? NGX_LOWAT_EVENT : 0))
385                 == NGX_ERROR)
386             {
387                 return NGX_ERROR;
388             }
389         }
390 
391         return NGX_OK;
392 
393     } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
394 
395         /* select, poll, /dev/poll */
396 
397         if (!wev->active && !wev->ready) {
398             if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
399                 == NGX_ERROR)
400             {
401                 return NGX_ERROR;
402             }
403 
404             return NGX_OK;
405         }
406 
407         if (wev->active && wev->ready) {
408             if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
409                 == NGX_ERROR)
410             {
411                 return NGX_ERROR;
412             }
413 
414             return NGX_OK;
415         }
416 
417     } else if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
418 
419         /* event ports */
420 
421         if (!wev->active && !wev->ready) {
422             if (ngx_add_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
423                 return NGX_ERROR;
424             }
425 
426             return NGX_OK;
427         }
428 
429         if (wev->oneshot && wev->ready) {
430             if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
431                 return NGX_ERROR;
432             }
433 
434             return NGX_OK;
435         }
436     }
437 
438     /* iocp */
439 
440     return NGX_OK;
441 }
442 
443 
444 static char *
ngx_event_init_conf(ngx_cycle_t * cycle,void * conf)445 ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
446 {
447 #if (NGX_HAVE_REUSEPORT)
448     ngx_uint_t        i;
449     ngx_listening_t  *ls;
450 #endif
451 
452     if (ngx_get_conf(cycle->conf_ctx, ngx_events_module) == NULL) {
453         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
454                       "no \"events\" section in configuration");
455         return NGX_CONF_ERROR;
456     }
457 
458     if (cycle->connection_n < cycle->listening.nelts + 1) {
459 
460         /*
461          * there should be at least one connection for each listening
462          * socket, plus an additional connection for channel
463          */
464 
465         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
466                       "%ui worker_connections are not enough "
467                       "for %ui listening sockets",
468                       cycle->connection_n, cycle->listening.nelts);
469 
470         return NGX_CONF_ERROR;
471     }
472 
473 #if (NGX_HAVE_REUSEPORT)
474 
475     ls = cycle->listening.elts;
476     for (i = 0; i < cycle->listening.nelts; i++) {
477 
478         if (!ls[i].reuseport || ls[i].worker != 0) {
479             continue;
480         }
481 
482         if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) {
483             return NGX_CONF_ERROR;
484         }
485 
486         /* cloning may change cycle->listening.elts */
487 
488         ls = cycle->listening.elts;
489     }
490 
491 #endif
492 
493     return NGX_CONF_OK;
494 }
495 
496 
497 static ngx_int_t
ngx_event_module_init(ngx_cycle_t * cycle)498 ngx_event_module_init(ngx_cycle_t *cycle)
499 {
500     void              ***cf;
501     u_char              *shared;
502     size_t               size, cl;
503     ngx_shm_t            shm;
504     ngx_time_t          *tp;
505     ngx_core_conf_t     *ccf;
506     ngx_event_conf_t    *ecf;
507 
508     cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module);
509     ecf = (*cf)[ngx_event_core_module.ctx_index];
510 
511     if (!ngx_test_config && ngx_process <= NGX_PROCESS_MASTER) {
512         ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
513                       "using the \"%s\" event method", ecf->name);
514     }
515 
516     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
517 
518     ngx_timer_resolution = ccf->timer_resolution;
519 
520 #if !(NGX_WIN32)
521     {
522     ngx_int_t      limit;
523     struct rlimit  rlmt;
524 
525     if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
526         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
527                       "getrlimit(RLIMIT_NOFILE) failed, ignored");
528 
529     } else {
530         if (ecf->connections > (ngx_uint_t) rlmt.rlim_cur
531             && (ccf->rlimit_nofile == NGX_CONF_UNSET
532                 || ecf->connections > (ngx_uint_t) ccf->rlimit_nofile))
533         {
534             limit = (ccf->rlimit_nofile == NGX_CONF_UNSET) ?
535                          (ngx_int_t) rlmt.rlim_cur : ccf->rlimit_nofile;
536 
537             ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
538                           "%ui worker_connections exceed "
539                           "open file resource limit: %i",
540                           ecf->connections, limit);
541         }
542     }
543     }
544 #endif /* !(NGX_WIN32) */
545 
546 
547     if (ccf->master == 0) {
548         return NGX_OK;
549     }
550 
551     if (ngx_accept_mutex_ptr) {
552         return NGX_OK;
553     }
554 
555 
556     /* cl should be equal to or greater than cache line size */
557 
558     cl = 128;
559 
560     size = cl            /* ngx_accept_mutex */
561            + cl          /* ngx_connection_counter */
562            + cl;         /* ngx_temp_number */
563 
564 #if (NGX_STAT_STUB)
565 
566     size += cl           /* ngx_stat_accepted */
567            + cl          /* ngx_stat_handled */
568            + cl          /* ngx_stat_requests */
569            + cl          /* ngx_stat_active */
570            + cl          /* ngx_stat_reading */
571            + cl          /* ngx_stat_writing */
572            + cl;         /* ngx_stat_waiting */
573 
574 #endif
575 
576     shm.size = size;
577     ngx_str_set(&shm.name, "nginx_shared_zone");
578     shm.log = cycle->log;
579 
580     if (ngx_shm_alloc(&shm) != NGX_OK) {
581         return NGX_ERROR;
582     }
583 
584     shared = shm.addr;
585 
586     ngx_accept_mutex_ptr = (ngx_atomic_t *) shared;
587     ngx_accept_mutex.spin = (ngx_uint_t) -1;
588 
589     if (ngx_shmtx_create(&ngx_accept_mutex, (ngx_shmtx_sh_t *) shared,
590                          cycle->lock_file.data)
591         != NGX_OK)
592     {
593         return NGX_ERROR;
594     }
595 
596     ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl);
597 
598     (void) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);
599 
600     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
601                    "counter: %p, %uA",
602                    ngx_connection_counter, *ngx_connection_counter);
603 
604     ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl);
605 
606     tp = ngx_timeofday();
607 
608     ngx_random_number = (tp->msec << 16) + ngx_pid;
609 
610 #if (NGX_STAT_STUB)
611 
612     ngx_stat_accepted = (ngx_atomic_t *) (shared + 3 * cl);
613     ngx_stat_handled = (ngx_atomic_t *) (shared + 4 * cl);
614     ngx_stat_requests = (ngx_atomic_t *) (shared + 5 * cl);
615     ngx_stat_active = (ngx_atomic_t *) (shared + 6 * cl);
616     ngx_stat_reading = (ngx_atomic_t *) (shared + 7 * cl);
617     ngx_stat_writing = (ngx_atomic_t *) (shared + 8 * cl);
618     ngx_stat_waiting = (ngx_atomic_t *) (shared + 9 * cl);
619 
620 #endif
621 
622 #if (NGX_HAVE_FSTACK)
623         ngx_schedule_timeout = ccf->schedule_timeout;
624 #endif
625 
626     return NGX_OK;
627 }
628 
629 
630 #if !(NGX_WIN32)
631 
632 static void
ngx_timer_signal_handler(int signo)633 ngx_timer_signal_handler(int signo)
634 {
635     ngx_event_timer_alarm = 1;
636 
637 #if 1
638     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, "timer signal");
639 #endif
640 }
641 
642 #endif
643 
644 #if (NGX_HAVE_FSTACK)
645 
646 extern ngx_event_actions_t   ngx_ff_host_event_actions;
647 
648 #endif
649 
650 static ngx_int_t
ngx_event_process_init(ngx_cycle_t * cycle)651 ngx_event_process_init(ngx_cycle_t *cycle)
652 {
653     ngx_uint_t           m, i;
654     ngx_event_t         *rev, *wev;
655     ngx_listening_t     *ls;
656     ngx_connection_t    *c, *next, *old;
657     ngx_core_conf_t     *ccf;
658     ngx_event_conf_t    *ecf;
659     ngx_event_module_t  *module;
660 
661     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
662     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
663 
664     if (ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex) {
665         ngx_use_accept_mutex = 1;
666         ngx_accept_mutex_held = 0;
667         ngx_accept_mutex_delay = ecf->accept_mutex_delay;
668 
669     } else {
670         ngx_use_accept_mutex = 0;
671     }
672 
673 #if (NGX_WIN32)
674 
675     /*
676      * disable accept mutex on win32 as it may cause deadlock if
677      * grabbed by a process which can't accept connections
678      */
679 
680     ngx_use_accept_mutex = 0;
681 
682 #endif
683 
684     ngx_queue_init(&ngx_posted_accept_events);
685     ngx_queue_init(&ngx_posted_events);
686 
687     if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
688         return NGX_ERROR;
689     }
690 
691     for (m = 0; cycle->modules[m]; m++) {
692         if (cycle->modules[m]->type != NGX_EVENT_MODULE) {
693             continue;
694         }
695 
696         if (cycle->modules[m]->ctx_index != ecf->use) {
697             continue;
698         }
699 
700         module = cycle->modules[m]->ctx;
701 
702         if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
703             /* fatal */
704             exit(2);
705         }
706 
707         break;
708     }
709 
710 #if (NGX_HAVE_FSTACK)
711     if (ngx_ff_host_event_actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
712         /* fatal */
713         exit(2);
714     }
715 #endif
716 
717 #if !(NGX_WIN32)
718 
719     if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
720         struct sigaction  sa;
721         struct itimerval  itv;
722 
723         ngx_memzero(&sa, sizeof(struct sigaction));
724         sa.sa_handler = ngx_timer_signal_handler;
725         sigemptyset(&sa.sa_mask);
726 
727         if (sigaction(SIGALRM, &sa, NULL) == -1) {
728             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
729                           "sigaction(SIGALRM) failed");
730             return NGX_ERROR;
731         }
732 
733         itv.it_interval.tv_sec = ngx_timer_resolution / 1000;
734         itv.it_interval.tv_usec = (ngx_timer_resolution % 1000) * 1000;
735         itv.it_value.tv_sec = ngx_timer_resolution / 1000;
736         itv.it_value.tv_usec = (ngx_timer_resolution % 1000 ) * 1000;
737 
738         if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
739             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
740                           "setitimer() failed");
741         }
742     }
743 
744     if (ngx_event_flags & NGX_USE_FD_EVENT) {
745         struct rlimit  rlmt;
746 
747         if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
748             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
749                           "getrlimit(RLIMIT_NOFILE) failed");
750             return NGX_ERROR;
751         }
752 
753         cycle->files_n = (ngx_uint_t) rlmt.rlim_cur;
754 
755 #if (NGX_HAVE_FSTACK)
756         cycle->files = ngx_calloc(sizeof(ngx_connection_t *) * cycle->files_n * 2,
757                                   cycle->log);
758 #else
759         cycle->files = ngx_calloc(sizeof(ngx_connection_t *) * cycle->files_n,
760                                   cycle->log);
761 #endif
762 
763         if (cycle->files == NULL) {
764             return NGX_ERROR;
765         }
766     }
767 
768 #else
769 
770     if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
771         ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
772                       "the \"timer_resolution\" directive is not supported "
773                       "with the configured event method, ignored");
774         ngx_timer_resolution = 0;
775     }
776 
777 #endif
778 
779     cycle->connections =
780         ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
781     if (cycle->connections == NULL) {
782         return NGX_ERROR;
783     }
784 
785     c = cycle->connections;
786 
787     cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
788                                    cycle->log);
789     if (cycle->read_events == NULL) {
790         return NGX_ERROR;
791     }
792 
793     rev = cycle->read_events;
794     for (i = 0; i < cycle->connection_n; i++) {
795         rev[i].closed = 1;
796         rev[i].instance = 1;
797     }
798 
799     cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
800                                     cycle->log);
801     if (cycle->write_events == NULL) {
802         return NGX_ERROR;
803     }
804 
805     wev = cycle->write_events;
806     for (i = 0; i < cycle->connection_n; i++) {
807         wev[i].closed = 1;
808     }
809 
810     i = cycle->connection_n;
811     next = NULL;
812 
813     do {
814         i--;
815 
816         c[i].data = next;
817         c[i].read = &cycle->read_events[i];
818         c[i].write = &cycle->write_events[i];
819         c[i].fd = (ngx_socket_t) -1;
820 
821         next = &c[i];
822     } while (i);
823 
824     cycle->free_connections = next;
825     cycle->free_connection_n = cycle->connection_n;
826 
827     /* for each listening socket */
828 
829     ls = cycle->listening.elts;
830     for (i = 0; i < cycle->listening.nelts; i++) {
831 
832 #if (NGX_HAVE_REUSEPORT)
833         if (ls[i].reuseport && ls[i].worker != ngx_worker) {
834             continue;
835         }
836 #endif
837 
838         c = ngx_get_connection(ls[i].fd, cycle->log);
839 
840         if (c == NULL) {
841             return NGX_ERROR;
842         }
843 
844         c->type = ls[i].type;
845         c->log = &ls[i].log;
846 
847         c->listening = &ls[i];
848         ls[i].connection = c;
849 
850         rev = c->read;
851 
852         rev->log = c->log;
853         rev->accept = 1;
854 
855 #if (NGX_HAVE_FSTACK)
856         /* Note when nginx running on fstack,
857             make sure that add the right fd to kqueue !! */
858         c->read->belong_to_host = c->write->belong_to_host = ls[i].belong_to_host;
859 #endif
860 
861 #if (NGX_HAVE_DEFERRED_ACCEPT)
862         rev->deferred_accept = ls[i].deferred_accept;
863 #endif
864 
865         if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
866             if (ls[i].previous) {
867 
868                 /*
869                  * delete the old accept events that were bound to
870                  * the old cycle read events array
871                  */
872 
873                 old = ls[i].previous->connection;
874 
875                 if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT)
876                     == NGX_ERROR)
877                 {
878                     return NGX_ERROR;
879                 }
880 
881                 old->fd = (ngx_socket_t) -1;
882             }
883         }
884 
885 #if (NGX_WIN32)
886 
887         if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
888             ngx_iocp_conf_t  *iocpcf;
889 
890             rev->handler = ngx_event_acceptex;
891 
892             if (ngx_use_accept_mutex) {
893                 continue;
894             }
895 
896             if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {
897                 return NGX_ERROR;
898             }
899 
900             ls[i].log.handler = ngx_acceptex_log_error;
901 
902             iocpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module);
903             if (ngx_event_post_acceptex(&ls[i], iocpcf->post_acceptex)
904                 == NGX_ERROR)
905             {
906                 return NGX_ERROR;
907             }
908 
909         } else {
910             rev->handler = ngx_event_accept;
911 
912             if (ngx_use_accept_mutex) {
913                 continue;
914             }
915 
916             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
917                 return NGX_ERROR;
918             }
919         }
920 
921 #else
922 
923         rev->handler = (c->type == SOCK_STREAM) ? ngx_event_accept
924                                                 : ngx_event_recvmsg;
925 
926 #if (NGX_HAVE_REUSEPORT)
927 
928         if (ls[i].reuseport) {
929             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
930                 return NGX_ERROR;
931             }
932 
933             continue;
934         }
935 
936 #endif
937 
938         if (ngx_use_accept_mutex) {
939             continue;
940         }
941 
942 #if (NGX_HAVE_EPOLLEXCLUSIVE)
943 
944         if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
945             && ccf->worker_processes > 1)
946         {
947             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT)
948                 == NGX_ERROR)
949             {
950                 return NGX_ERROR;
951             }
952 
953             continue;
954         }
955 
956 #endif
957 
958         if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
959             return NGX_ERROR;
960         }
961 
962 #endif
963 
964     }
965 
966     return NGX_OK;
967 }
968 
969 
970 ngx_int_t
ngx_send_lowat(ngx_connection_t * c,size_t lowat)971 ngx_send_lowat(ngx_connection_t *c, size_t lowat)
972 {
973     int  sndlowat;
974 
975 #if (NGX_HAVE_LOWAT_EVENT)
976 
977     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
978         c->write->available = lowat;
979         return NGX_OK;
980     }
981 
982 #endif
983 
984     if (lowat == 0 || c->sndlowat) {
985         return NGX_OK;
986     }
987 
988     sndlowat = (int) lowat;
989 
990     if (setsockopt(c->fd, SOL_SOCKET, SO_SNDLOWAT,
991                    (const void *) &sndlowat, sizeof(int))
992         == -1)
993     {
994         ngx_connection_error(c, ngx_socket_errno,
995                              "setsockopt(SO_SNDLOWAT) failed");
996         return NGX_ERROR;
997     }
998 
999     c->sndlowat = 1;
1000 
1001     return NGX_OK;
1002 }
1003 
1004 
1005 static char *
ngx_events_block(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)1006 ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1007 {
1008     char                 *rv;
1009     void               ***ctx;
1010     ngx_uint_t            i;
1011     ngx_conf_t            pcf;
1012     ngx_event_module_t   *m;
1013 
1014     if (*(void **) conf) {
1015         return "is duplicate";
1016     }
1017 
1018     /* count the number of the event modules and set up their indices */
1019 
1020     ngx_event_max_module = ngx_count_modules(cf->cycle, NGX_EVENT_MODULE);
1021 
1022     ctx = ngx_pcalloc(cf->pool, sizeof(void *));
1023     if (ctx == NULL) {
1024         return NGX_CONF_ERROR;
1025     }
1026 
1027     *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
1028     if (*ctx == NULL) {
1029         return NGX_CONF_ERROR;
1030     }
1031 
1032     *(void **) conf = ctx;
1033 
1034     for (i = 0; cf->cycle->modules[i]; i++) {
1035         if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) {
1036             continue;
1037         }
1038 
1039         m = cf->cycle->modules[i]->ctx;
1040 
1041         if (m->create_conf) {
1042             (*ctx)[cf->cycle->modules[i]->ctx_index] =
1043                                                      m->create_conf(cf->cycle);
1044             if ((*ctx)[cf->cycle->modules[i]->ctx_index] == NULL) {
1045                 return NGX_CONF_ERROR;
1046             }
1047         }
1048     }
1049 
1050     pcf = *cf;
1051     cf->ctx = ctx;
1052     cf->module_type = NGX_EVENT_MODULE;
1053     cf->cmd_type = NGX_EVENT_CONF;
1054 
1055     rv = ngx_conf_parse(cf, NULL);
1056 
1057     *cf = pcf;
1058 
1059     if (rv != NGX_CONF_OK) {
1060         return rv;
1061     }
1062 
1063     for (i = 0; cf->cycle->modules[i]; i++) {
1064         if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) {
1065             continue;
1066         }
1067 
1068         m = cf->cycle->modules[i]->ctx;
1069 
1070         if (m->init_conf) {
1071             rv = m->init_conf(cf->cycle,
1072                               (*ctx)[cf->cycle->modules[i]->ctx_index]);
1073             if (rv != NGX_CONF_OK) {
1074                 return rv;
1075             }
1076         }
1077     }
1078 
1079     return NGX_CONF_OK;
1080 }
1081 
1082 
1083 static char *
ngx_event_connections(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)1084 ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1085 {
1086     ngx_event_conf_t  *ecf = conf;
1087 
1088     ngx_str_t  *value;
1089 
1090     if (ecf->connections != NGX_CONF_UNSET_UINT) {
1091         return "is duplicate";
1092     }
1093 
1094     value = cf->args->elts;
1095     ecf->connections = ngx_atoi(value[1].data, value[1].len);
1096     if (ecf->connections == (ngx_uint_t) NGX_ERROR) {
1097         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1098                            "invalid number \"%V\"", &value[1]);
1099 
1100         return NGX_CONF_ERROR;
1101     }
1102 
1103     cf->cycle->connection_n = ecf->connections;
1104 
1105     return NGX_CONF_OK;
1106 }
1107 
1108 
1109 static char *
ngx_event_use(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)1110 ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1111 {
1112     ngx_event_conf_t  *ecf = conf;
1113 
1114     ngx_int_t             m;
1115     ngx_str_t            *value;
1116     ngx_event_conf_t     *old_ecf;
1117     ngx_event_module_t   *module;
1118 
1119     if (ecf->use != NGX_CONF_UNSET_UINT) {
1120         return "is duplicate";
1121     }
1122 
1123     value = cf->args->elts;
1124 
1125     if (cf->cycle->old_cycle->conf_ctx) {
1126         old_ecf = ngx_event_get_conf(cf->cycle->old_cycle->conf_ctx,
1127                                      ngx_event_core_module);
1128     } else {
1129         old_ecf = NULL;
1130     }
1131 
1132 
1133     for (m = 0; cf->cycle->modules[m]; m++) {
1134         if (cf->cycle->modules[m]->type != NGX_EVENT_MODULE) {
1135             continue;
1136         }
1137 
1138         module = cf->cycle->modules[m]->ctx;
1139         if (module->name->len == value[1].len) {
1140             if (ngx_strcmp(module->name->data, value[1].data) == 0) {
1141                 ecf->use = cf->cycle->modules[m]->ctx_index;
1142                 ecf->name = module->name->data;
1143 
1144                 if (ngx_process == NGX_PROCESS_SINGLE
1145                     && old_ecf
1146                     && old_ecf->use != ecf->use)
1147                 {
1148                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1149                                "when the server runs without a master process "
1150                                "the \"%V\" event type must be the same as "
1151                                "in previous configuration - \"%s\" "
1152                                "and it cannot be changed on the fly, "
1153                                "to change it you need to stop server "
1154                                "and start it again",
1155                                &value[1], old_ecf->name);
1156 
1157                     return NGX_CONF_ERROR;
1158                 }
1159 
1160                 return NGX_CONF_OK;
1161             }
1162         }
1163     }
1164 
1165     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1166                        "invalid event type \"%V\"", &value[1]);
1167 
1168     return NGX_CONF_ERROR;
1169 }
1170 
1171 
1172 static char *
ngx_event_debug_connection(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)1173 ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1174 {
1175 #if (NGX_DEBUG)
1176     ngx_event_conf_t  *ecf = conf;
1177 
1178     ngx_int_t             rc;
1179     ngx_str_t            *value;
1180     ngx_url_t             u;
1181     ngx_cidr_t            c, *cidr;
1182     ngx_uint_t            i;
1183     struct sockaddr_in   *sin;
1184 #if (NGX_HAVE_INET6)
1185     struct sockaddr_in6  *sin6;
1186 #endif
1187 
1188     value = cf->args->elts;
1189 
1190 #if (NGX_HAVE_UNIX_DOMAIN)
1191 
1192     if (ngx_strcmp(value[1].data, "unix:") == 0) {
1193         cidr = ngx_array_push(&ecf->debug_connection);
1194         if (cidr == NULL) {
1195             return NGX_CONF_ERROR;
1196         }
1197 
1198         cidr->family = AF_UNIX;
1199         return NGX_CONF_OK;
1200     }
1201 
1202 #endif
1203 
1204     rc = ngx_ptocidr(&value[1], &c);
1205 
1206     if (rc != NGX_ERROR) {
1207         if (rc == NGX_DONE) {
1208             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1209                                "low address bits of %V are meaningless",
1210                                &value[1]);
1211         }
1212 
1213         cidr = ngx_array_push(&ecf->debug_connection);
1214         if (cidr == NULL) {
1215             return NGX_CONF_ERROR;
1216         }
1217 
1218         *cidr = c;
1219 
1220         return NGX_CONF_OK;
1221     }
1222 
1223     ngx_memzero(&u, sizeof(ngx_url_t));
1224     u.host = value[1];
1225 
1226     if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
1227         if (u.err) {
1228             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1229                                "%s in debug_connection \"%V\"",
1230                                u.err, &u.host);
1231         }
1232 
1233         return NGX_CONF_ERROR;
1234     }
1235 
1236     cidr = ngx_array_push_n(&ecf->debug_connection, u.naddrs);
1237     if (cidr == NULL) {
1238         return NGX_CONF_ERROR;
1239     }
1240 
1241     ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t));
1242 
1243     for (i = 0; i < u.naddrs; i++) {
1244         cidr[i].family = u.addrs[i].sockaddr->sa_family;
1245 
1246         switch (cidr[i].family) {
1247 
1248 #if (NGX_HAVE_INET6)
1249         case AF_INET6:
1250             sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr;
1251             cidr[i].u.in6.addr = sin6->sin6_addr;
1252             ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16);
1253             break;
1254 #endif
1255 
1256         default: /* AF_INET */
1257             sin = (struct sockaddr_in *) u.addrs[i].sockaddr;
1258             cidr[i].u.in.addr = sin->sin_addr.s_addr;
1259             cidr[i].u.in.mask = 0xffffffff;
1260             break;
1261         }
1262     }
1263 
1264 #else
1265 
1266     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1267                        "\"debug_connection\" is ignored, you need to rebuild "
1268                        "nginx using --with-debug option to enable it");
1269 
1270 #endif
1271 
1272     return NGX_CONF_OK;
1273 }
1274 
1275 
1276 static void *
ngx_event_core_create_conf(ngx_cycle_t * cycle)1277 ngx_event_core_create_conf(ngx_cycle_t *cycle)
1278 {
1279     ngx_event_conf_t  *ecf;
1280 
1281     ecf = ngx_palloc(cycle->pool, sizeof(ngx_event_conf_t));
1282     if (ecf == NULL) {
1283         return NULL;
1284     }
1285 
1286     ecf->connections = NGX_CONF_UNSET_UINT;
1287     ecf->use = NGX_CONF_UNSET_UINT;
1288     ecf->multi_accept = NGX_CONF_UNSET;
1289     ecf->accept_mutex = NGX_CONF_UNSET;
1290     ecf->accept_mutex_delay = NGX_CONF_UNSET_MSEC;
1291     ecf->name = (void *) NGX_CONF_UNSET;
1292 
1293 #if (NGX_DEBUG)
1294 
1295     if (ngx_array_init(&ecf->debug_connection, cycle->pool, 4,
1296                        sizeof(ngx_cidr_t)) == NGX_ERROR)
1297     {
1298         return NULL;
1299     }
1300 
1301 #endif
1302 
1303     return ecf;
1304 }
1305 
1306 
1307 static char *
ngx_event_core_init_conf(ngx_cycle_t * cycle,void * conf)1308 ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf)
1309 {
1310     ngx_event_conf_t  *ecf = conf;
1311 
1312 #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL)
1313     int                  fd;
1314 #endif
1315     ngx_int_t            i;
1316     ngx_module_t        *module;
1317     ngx_event_module_t  *event_module;
1318 
1319     module = NULL;
1320 
1321 #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL)
1322 
1323     fd = epoll_create(100);
1324 
1325     if (fd != -1) {
1326         (void) close(fd);
1327         module = &ngx_epoll_module;
1328 
1329     } else if (ngx_errno != NGX_ENOSYS) {
1330         module = &ngx_epoll_module;
1331     }
1332 
1333 #endif
1334 
1335 #if (NGX_HAVE_DEVPOLL) && !(NGX_TEST_BUILD_DEVPOLL)
1336 
1337     module = &ngx_devpoll_module;
1338 
1339 #endif
1340 
1341 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_FSTACK)
1342 
1343     module = &ngx_kqueue_module;
1344 
1345 #endif
1346 
1347 #if (NGX_HAVE_SELECT)
1348 
1349     if (module == NULL) {
1350         module = &ngx_select_module;
1351     }
1352 
1353 #endif
1354 
1355     if (module == NULL) {
1356         for (i = 0; cycle->modules[i]; i++) {
1357 
1358             if (cycle->modules[i]->type != NGX_EVENT_MODULE) {
1359                 continue;
1360             }
1361 
1362             event_module = cycle->modules[i]->ctx;
1363 
1364             if (ngx_strcmp(event_module->name->data, event_core_name.data) == 0)
1365             {
1366                 continue;
1367             }
1368 
1369             module = cycle->modules[i];
1370             break;
1371         }
1372     }
1373 
1374     if (module == NULL) {
1375         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "no events module found");
1376         return NGX_CONF_ERROR;
1377     }
1378 
1379     ngx_conf_init_uint_value(ecf->connections, DEFAULT_CONNECTIONS);
1380     cycle->connection_n = ecf->connections;
1381 
1382     ngx_conf_init_uint_value(ecf->use, module->ctx_index);
1383 
1384     event_module = module->ctx;
1385     ngx_conf_init_ptr_value(ecf->name, event_module->name->data);
1386 
1387     ngx_conf_init_value(ecf->multi_accept, 0);
1388     ngx_conf_init_value(ecf->accept_mutex, 0);
1389     ngx_conf_init_msec_value(ecf->accept_mutex_delay, 500);
1390 
1391     return NGX_CONF_OK;
1392 }
1393