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