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