Mercurial > hg > nginx
comparison src/event/modules/ngx_rtsig_module.c @ 351:af4c6b45a687
nginx-0.0.4-2004-06-10-22:36:57 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 10 Jun 2004 18:36:57 +0000 |
parents | 7b96b7f8a6af |
children | 694d7ddc3599 |
comparison
equal
deleted
inserted
replaced
350:7b96b7f8a6af | 351:af4c6b45a687 |
---|---|
25 | 25 |
26 #endif | 26 #endif |
27 | 27 |
28 | 28 |
29 typedef struct { | 29 typedef struct { |
30 int signo; | 30 int signo; |
31 ngx_int_t overflow_events; | |
32 ngx_int_t overflow_test; | |
33 ngx_int_t overflow_threshold; | |
31 } ngx_rtsig_conf_t; | 34 } ngx_rtsig_conf_t; |
32 | 35 |
33 | 36 |
34 extern ngx_event_module_t ngx_poll_module_ctx; | 37 extern ngx_event_module_t ngx_poll_module_ctx; |
35 | 38 |
42 | 45 |
43 static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle); | 46 static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle); |
44 static char *ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf); | 47 static char *ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf); |
45 | 48 |
46 | 49 |
47 static sigset_t set; | 50 static sigset_t set; |
48 static ngx_uint_t overflow, current; | 51 static ngx_uint_t overflow, overflow_current; |
52 static struct pollfd *overflow_list; | |
49 | 53 |
50 | 54 |
51 static ngx_str_t rtsig_name = ngx_string("rtsig"); | 55 static ngx_str_t rtsig_name = ngx_string("rtsig"); |
56 | |
57 static ngx_conf_num_bounds_t ngx_overflow_threshold_bounds = { | |
58 ngx_conf_check_num_bounds, 2, 10 | |
59 }; | |
60 | |
52 | 61 |
53 static ngx_command_t ngx_rtsig_commands[] = { | 62 static ngx_command_t ngx_rtsig_commands[] = { |
54 | 63 |
55 {ngx_string("rtsig_signo"), | 64 {ngx_string("rtsig_signo"), |
56 NGX_EVENT_CONF|NGX_CONF_TAKE1, | 65 NGX_EVENT_CONF|NGX_CONF_TAKE1, |
57 ngx_conf_set_num_slot, | 66 ngx_conf_set_num_slot, |
58 0, | 67 0, |
59 offsetof(ngx_rtsig_conf_t, signo), | 68 offsetof(ngx_rtsig_conf_t, signo), |
60 NULL}, | 69 NULL}, |
70 | |
71 {ngx_string("rtsig_overflow_events"), | |
72 NGX_EVENT_CONF|NGX_CONF_TAKE1, | |
73 ngx_conf_set_num_slot, | |
74 0, | |
75 offsetof(ngx_rtsig_conf_t, overflow_events), | |
76 NULL}, | |
77 | |
78 {ngx_string("rtsig_overflow_test"), | |
79 NGX_EVENT_CONF|NGX_CONF_TAKE1, | |
80 ngx_conf_set_num_slot, | |
81 0, | |
82 offsetof(ngx_rtsig_conf_t, overflow_test), | |
83 NULL}, | |
84 | |
85 {ngx_string("rtsig_overflow_threshold"), | |
86 NGX_EVENT_CONF|NGX_CONF_TAKE1, | |
87 ngx_conf_set_num_slot, | |
88 0, | |
89 offsetof(ngx_rtsig_conf_t, overflow_threshold), | |
90 &ngx_overflow_threshold_bounds}, | |
61 | 91 |
62 ngx_null_command | 92 ngx_null_command |
63 }; | 93 }; |
64 | 94 |
65 | 95 |
108 sigaddset(&set, SIGIO); | 138 sigaddset(&set, SIGIO); |
109 | 139 |
110 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { | 140 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { |
111 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 141 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, |
112 "sigprocmask() failed"); | 142 "sigprocmask() failed"); |
143 return NGX_ERROR; | |
144 } | |
145 | |
146 if (overflow_list) { | |
147 ngx_free(overflow_list); | |
148 } | |
149 | |
150 overflow_list = ngx_alloc(sizeof(struct pollfd) * rtscf->overflow_events, | |
151 cycle->log); | |
152 if (overflow_list == NULL) { | |
113 return NGX_ERROR; | 153 return NGX_ERROR; |
114 } | 154 } |
115 | 155 |
116 ngx_io = ngx_os_io; | 156 ngx_io = ngx_os_io; |
117 | 157 |
337 | 377 |
338 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module); | 378 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module); |
339 | 379 |
340 if (signo == rtscf->signo || signo == rtscf->signo + 1) { | 380 if (signo == rtscf->signo || signo == rtscf->signo + 1) { |
341 | 381 |
342 if (overflow && (ngx_uint_t) si.si_fd > current) { | 382 if (overflow && (ngx_uint_t) si.si_fd > overflow_current) { |
343 return NGX_OK; | 383 return NGX_OK; |
344 } | 384 } |
345 | 385 |
346 /* TODO: old_cycles */ | 386 /* TODO: old_cycles */ |
347 | 387 |
439 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 479 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
440 "sigaction(%d, SIG_DFL) failed", rtscf->signo + 1); | 480 "sigaction(%d, SIG_DFL) failed", rtscf->signo + 1); |
441 } | 481 } |
442 | 482 |
443 overflow = 1; | 483 overflow = 1; |
444 current = 0; | 484 overflow_current = 0; |
445 ngx_event_actions.process = ngx_rtsig_process_overflow; | 485 ngx_event_actions.process = ngx_rtsig_process_overflow; |
446 | 486 |
447 return NGX_OK; | 487 return NGX_OK; |
448 | 488 |
449 } else if (signo != -1) { | 489 } else if (signo != -1) { |
471 return NGX_OK; | 511 return NGX_OK; |
472 } | 512 } |
473 } | 513 } |
474 | 514 |
475 | 515 |
516 /* TODO: old cylces */ | |
517 | |
476 static ngx_int_t ngx_rtsig_process_overflow(ngx_cycle_t *cycle) | 518 static ngx_int_t ngx_rtsig_process_overflow(ngx_cycle_t *cycle) |
477 { | 519 { |
478 int name[2], len, rtsig_max, rtsig_nr; | 520 int name[2], len, rtsig_max, rtsig_nr, events, ready; |
479 ngx_uint_t i, n; | 521 ngx_int_t tested, n, i; |
522 ngx_err_t err; | |
480 ngx_connection_t *c; | 523 ngx_connection_t *c; |
481 | 524 ngx_rtsig_conf_t *rtscf; |
482 /* TODO: old cylces */ | 525 |
483 | 526 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module); |
484 n = 0; | 527 |
485 c = cycle->connections; | 528 tested = 0; |
486 for (current = 0; current < cycle->connection_n; current++) { | 529 |
487 | 530 for ( ;; ) { |
488 i = current; | 531 |
489 | 532 n = 0; |
490 if (c[i].fd == -1) { | 533 while (n < rtscf->overflow_events) { |
534 | |
535 if (overflow_current == cycle->connection_n) { | |
536 break; | |
537 } | |
538 | |
539 c = &cycle->connections[overflow_current++]; | |
540 | |
541 if (c->fd == -1) { | |
542 continue; | |
543 } | |
544 | |
545 events = 0; | |
546 | |
547 if (c->read->active && c->read->event_handler) { | |
548 events |= POLLIN; | |
549 } | |
550 | |
551 if (c->write->active && c->write->event_handler) { | |
552 events |= POLLOUT; | |
553 } | |
554 | |
555 if (events == 0) { | |
556 continue; | |
557 } | |
558 | |
559 overflow_list[n].fd = c->fd; | |
560 overflow_list[n].events = events; | |
561 overflow_list[n].revents = 0; | |
562 n++; | |
563 } | |
564 | |
565 if (n == 0) { | |
566 break; | |
567 } | |
568 | |
569 for ( ;; ) { | |
570 ready = poll(overflow_list, n, 0); | |
571 | |
572 if (ready == -1) { | |
573 err = ngx_errno; | |
574 ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, | |
575 cycle->log, 0, | |
576 "poll() failed while the overflow recover"); | |
577 | |
578 if (err == NGX_EINTR) { | |
579 continue; | |
580 } | |
581 } | |
582 | |
583 break; | |
584 } | |
585 | |
586 if (ready <= 0) { | |
491 continue; | 587 continue; |
492 } | 588 } |
493 | 589 |
494 if (c[i].read->active && c[i].read->event_handler) { | 590 for (i = 0; i < n; i++) { |
495 n++; | 591 c = &cycle->connections[overflow_list[i].fd]; |
496 c[i].read->ready = 1; | 592 |
497 | 593 if (overflow_list[i].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) { |
498 if (!ngx_threaded) { | 594 tested++; |
499 c[i].read->event_handler(c[i].read); | 595 c->read->ready = 1; |
500 | 596 |
501 } else { | 597 if (!ngx_threaded) { |
502 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { | 598 c->read->event_handler(c->read); |
503 return NGX_ERROR; | 599 |
600 } else { | |
601 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { | |
602 return NGX_ERROR; | |
603 } | |
604 | |
605 ngx_post_event(c->read); | |
606 c->read->returned_instance = c->read->instance; | |
607 | |
608 ngx_mutex_unlock(ngx_posted_events_mutex); | |
504 } | 609 } |
505 | 610 } |
506 ngx_post_event(c[i].read); | 611 |
507 | 612 if (overflow_list[i].revents & (POLLOUT|POLLERR|POLLHUP|POLLNVAL)) { |
508 ngx_mutex_unlock(ngx_posted_events_mutex); | 613 tested++; |
509 } | 614 c->write->ready = 1; |
510 } | |
511 | |
512 if (c[i].write->active && c[i].write->event_handler) { | |
513 n++; | |
514 c[i].write->ready = 1; | |
515 | 615 |
516 if (!ngx_threaded) { | 616 if (!ngx_threaded) { |
517 c[i].write->event_handler(c[i].write); | 617 c->write->event_handler(c->write); |
518 | 618 |
519 } else { | 619 } else { |
520 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { | 620 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { |
521 return NGX_ERROR; | 621 return NGX_ERROR; |
522 } | 622 } |
523 | 623 |
524 ngx_post_event(c[i].write); | 624 ngx_post_event(c->write); |
525 | 625 c->write->returned_instance = c->write->instance; |
526 ngx_mutex_unlock(ngx_posted_events_mutex); | 626 |
527 } | 627 ngx_mutex_unlock(ngx_posted_events_mutex); |
528 } | 628 } |
529 | 629 } |
530 if (n && (n % 100 == 0)) { | 630 } |
631 | |
632 if (tested >= rtscf->overflow_test) { | |
531 | 633 |
532 /* | 634 /* |
533 * Check the current rt queue length to prevent the new overflow. | 635 * Check the current rt queue length to prevent the new overflow. |
534 * | 636 * |
535 * Learn the /proc/sys/kernel/rtsig-max value because | 637 * Learn the /proc/sys/kernel/rtsig-max value because |
553 "sysctl(KERN_RTSIGNR) failed"); | 655 "sysctl(KERN_RTSIGNR) failed"); |
554 return NGX_ERROR; | 656 return NGX_ERROR; |
555 } | 657 } |
556 | 658 |
557 /* | 659 /* |
558 * drain rt signal queue if the /proc/sys/kernel/rtsig-nr | 660 * drain rt signal queue if the /proc/sys/kernel/rtsig-nr is bigger |
559 * is bigger than "/proc/sys/kernel/rtsig-max / 4" | 661 * than "/proc/sys/kernel/rtsig-max / rtsig_overflow_threshold" |
560 */ | 662 */ |
561 | 663 |
562 if (rtsig_max / 4 < rtsig_nr) { | 664 if (rtsig_max / rtscf->overflow_threshold < rtsig_nr) { |
563 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 665 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
564 "rtsig queue state: %d/%d", rtsig_nr, rtsig_max); | 666 "rtsig queue state: %d/%d", rtsig_nr, rtsig_max); |
565 while (ngx_rtsig_process_events(cycle) == NGX_OK) { /* void */ } | 667 while (ngx_rtsig_process_events(cycle) == NGX_OK) { /* void */ } |
566 } | 668 } |
669 | |
670 tested = 0; | |
567 } | 671 } |
568 } | 672 } |
569 | 673 |
570 if (!ngx_threaded) { | 674 if (!ngx_threaded) { |
571 ngx_event_process_posted(cycle); | 675 ngx_event_process_posted(cycle); |
587 | 691 |
588 ngx_test_null(rtscf, ngx_palloc(cycle->pool, sizeof(ngx_rtsig_conf_t)), | 692 ngx_test_null(rtscf, ngx_palloc(cycle->pool, sizeof(ngx_rtsig_conf_t)), |
589 NGX_CONF_ERROR); | 693 NGX_CONF_ERROR); |
590 | 694 |
591 rtscf->signo = NGX_CONF_UNSET; | 695 rtscf->signo = NGX_CONF_UNSET; |
696 rtscf->overflow_events = NGX_CONF_UNSET; | |
697 rtscf->overflow_test = NGX_CONF_UNSET; | |
698 rtscf->overflow_threshold = NGX_CONF_UNSET; | |
592 | 699 |
593 return rtscf; | 700 return rtscf; |
594 } | 701 } |
595 | 702 |
596 | 703 |
599 ngx_rtsig_conf_t *rtscf = conf; | 706 ngx_rtsig_conf_t *rtscf = conf; |
600 | 707 |
601 /* LinuxThreads use the first 3 RT signals */ | 708 /* LinuxThreads use the first 3 RT signals */ |
602 ngx_conf_init_value(rtscf->signo, SIGRTMIN + 10); | 709 ngx_conf_init_value(rtscf->signo, SIGRTMIN + 10); |
603 | 710 |
711 ngx_conf_init_value(rtscf->overflow_events, 16); | |
712 ngx_conf_init_value(rtscf->overflow_test, 100); | |
713 ngx_conf_init_value(rtscf->overflow_threshold, 4); | |
714 | |
604 return NGX_CONF_OK; | 715 return NGX_CONF_OK; |
605 } | 716 } |