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