3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_event.h>
13 #if (NGX_TEST_BUILD_RTSIG)
18 #define si_fd __pad[0]
23 #define si_fd _reason.__spare__.__spare2__[0]
26 #define si_fd __spare__[0]
32 #define KERN_RTSIGNR 30
33 #define KERN_RTSIGMAX 31
35 int sigtimedwait(const sigset_t
*set
, siginfo_t
*info
,
36 const struct timespec
*timeout
);
38 int sigtimedwait(const sigset_t
*set
, siginfo_t
*info
,
39 const struct timespec
*timeout
)
44 int ngx_linux_rtsig_max
;
51 ngx_uint_t overflow_events
;
52 ngx_uint_t overflow_test
;
53 ngx_uint_t overflow_threshold
;
57 extern ngx_event_module_t ngx_poll_module_ctx
;
59 static ngx_int_t
ngx_rtsig_init(ngx_cycle_t
*cycle
, ngx_msec_t timer
);
60 static void ngx_rtsig_done(ngx_cycle_t
*cycle
);
61 static ngx_int_t
ngx_rtsig_add_connection(ngx_connection_t
*c
);
62 static ngx_int_t
ngx_rtsig_del_connection(ngx_connection_t
*c
,
64 static ngx_int_t
ngx_rtsig_process_events(ngx_cycle_t
*cycle
,
65 ngx_msec_t timer
, ngx_uint_t flags
);
66 static ngx_int_t
ngx_rtsig_process_overflow(ngx_cycle_t
*cycle
,
67 ngx_msec_t timer
, ngx_uint_t flags
);
69 static void *ngx_rtsig_create_conf(ngx_cycle_t
*cycle
);
70 static char *ngx_rtsig_init_conf(ngx_cycle_t
*cycle
, void *conf
);
71 static char *ngx_check_ngx_overflow_threshold_bounds(ngx_conf_t
*cf
,
72 void *post
, void *data
);
76 static ngx_uint_t overflow
, overflow_current
;
77 static struct pollfd
*overflow_list
;
80 static ngx_str_t rtsig_name
= ngx_string("rtsig");
82 static ngx_conf_num_bounds_t ngx_overflow_threshold_bounds
= {
83 ngx_check_ngx_overflow_threshold_bounds
, 2, 10
87 static ngx_command_t ngx_rtsig_commands
[] = {
89 { ngx_string("rtsig_signo"),
90 NGX_EVENT_CONF
|NGX_CONF_TAKE1
,
91 ngx_conf_set_num_slot
,
93 offsetof(ngx_rtsig_conf_t
, signo
),
96 { ngx_string("rtsig_overflow_events"),
97 NGX_EVENT_CONF
|NGX_CONF_TAKE1
,
98 ngx_conf_set_num_slot
,
100 offsetof(ngx_rtsig_conf_t
, overflow_events
),
103 { ngx_string("rtsig_overflow_test"),
104 NGX_EVENT_CONF
|NGX_CONF_TAKE1
,
105 ngx_conf_set_num_slot
,
107 offsetof(ngx_rtsig_conf_t
, overflow_test
),
110 { ngx_string("rtsig_overflow_threshold"),
111 NGX_EVENT_CONF
|NGX_CONF_TAKE1
,
112 ngx_conf_set_num_slot
,
114 offsetof(ngx_rtsig_conf_t
, overflow_threshold
),
115 &ngx_overflow_threshold_bounds
},
121 ngx_event_module_t ngx_rtsig_module_ctx
= {
123 ngx_rtsig_create_conf
, /* create configuration */
124 ngx_rtsig_init_conf
, /* init configuration */
127 NULL
, /* add an event */
128 NULL
, /* delete an event */
129 NULL
, /* enable an event */
130 NULL
, /* disable an event */
131 ngx_rtsig_add_connection
, /* add an connection */
132 ngx_rtsig_del_connection
, /* delete an connection */
133 NULL
, /* process the changes */
134 ngx_rtsig_process_events
, /* process the events */
135 ngx_rtsig_init
, /* init the events */
136 ngx_rtsig_done
, /* done the events */
141 ngx_module_t ngx_rtsig_module
= {
143 &ngx_rtsig_module_ctx
, /* module context */
144 ngx_rtsig_commands
, /* module directives */
145 NGX_EVENT_MODULE
, /* module type */
146 NULL
, /* init master */
147 NULL
, /* init module */
148 NULL
, /* init process */
149 NULL
, /* init thread */
150 NULL
, /* exit thread */
151 NULL
, /* exit process */
152 NULL
, /* exit master */
153 NGX_MODULE_V1_PADDING
158 ngx_rtsig_init(ngx_cycle_t
*cycle
, ngx_msec_t timer
)
160 ngx_rtsig_conf_t
*rtscf
;
162 rtscf
= ngx_event_get_conf(cycle
->conf_ctx
, ngx_rtsig_module
);
165 sigaddset(&set
, (int) rtscf
->signo
);
166 sigaddset(&set
, (int) rtscf
->signo
+ 1);
167 sigaddset(&set
, SIGIO
);
168 sigaddset(&set
, SIGALRM
);
170 if (sigprocmask(SIG_BLOCK
, &set
, NULL
) == -1) {
171 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
172 "sigprocmask() failed");
177 ngx_free(overflow_list
);
180 overflow_list
= ngx_alloc(sizeof(struct pollfd
) * rtscf
->overflow_events
,
182 if (overflow_list
== NULL
) {
188 ngx_event_actions
= ngx_rtsig_module_ctx
.actions
;
190 ngx_event_flags
= NGX_USE_RTSIG_EVENT
191 |NGX_USE_GREEDY_EVENT
199 ngx_rtsig_done(ngx_cycle_t
*cycle
)
201 ngx_free(overflow_list
);
203 overflow_list
= NULL
;
208 ngx_rtsig_add_connection(ngx_connection_t
*c
)
211 ngx_rtsig_conf_t
*rtscf
;
213 if (c
->read
->accept
&& c
->read
->disabled
) {
215 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
216 "rtsig enable connection: fd:%d", c
->fd
);
218 if (fcntl(c
->fd
, F_SETOWN
, ngx_pid
) == -1) {
219 ngx_log_error(NGX_LOG_ALERT
, c
->log
, ngx_errno
,
220 "fcntl(F_SETOWN) failed");
225 c
->read
->disabled
= 0;
228 rtscf
= ngx_event_get_conf(ngx_cycle
->conf_ctx
, ngx_rtsig_module
);
230 signo
= rtscf
->signo
+ c
->read
->instance
;
232 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
233 "rtsig add connection: fd:%d signo:%ui", c
->fd
, signo
);
235 if (fcntl(c
->fd
, F_SETFL
, O_RDWR
|O_NONBLOCK
|O_ASYNC
) == -1) {
236 ngx_log_error(NGX_LOG_ALERT
, c
->log
, ngx_errno
,
237 "fcntl(O_RDWR|O_NONBLOCK|O_ASYNC) failed");
241 if (fcntl(c
->fd
, F_SETSIG
, (int) signo
) == -1) {
242 ngx_log_error(NGX_LOG_ALERT
, c
->log
, ngx_errno
,
243 "fcntl(F_SETSIG) failed");
247 if (fcntl(c
->fd
, F_SETOWN
, ngx_pid
) == -1) {
248 ngx_log_error(NGX_LOG_ALERT
, c
->log
, ngx_errno
,
249 "fcntl(F_SETOWN) failed");
253 #if (NGX_HAVE_ONESIGFD)
254 if (fcntl(c
->fd
, F_SETAUXFL
, O_ONESIGFD
) == -1) {
255 ngx_log_error(NGX_LOG_ALERT
, c
->log
, ngx_errno
,
256 "fcntl(F_SETAUXFL) failed");
262 c
->write
->active
= 1;
269 ngx_rtsig_del_connection(ngx_connection_t
*c
, ngx_uint_t flags
)
271 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
272 "rtsig del connection: fd:%d", c
->fd
);
274 if ((flags
& NGX_DISABLE_EVENT
) && c
->read
->accept
) {
276 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
277 "rtsig disable connection: fd:%d", c
->fd
);
280 c
->read
->disabled
= 1;
284 if (flags
& NGX_CLOSE_EVENT
) {
286 c
->write
->active
= 0;
290 if (fcntl(c
->fd
, F_SETFL
, O_RDWR
|O_NONBLOCK
) == -1) {
291 ngx_log_error(NGX_LOG_ALERT
, c
->log
, ngx_errno
,
292 "fcntl(O_RDWR|O_NONBLOCK) failed");
297 c
->write
->active
= 0;
304 ngx_rtsig_process_events(ngx_cycle_t
*cycle
, ngx_msec_t timer
, ngx_uint_t flags
)
310 ngx_event_t
*rev
, *wev
, **queue
;
311 struct timespec ts
, *tp
;
314 ngx_rtsig_conf_t
*rtscf
;
316 if (timer
== NGX_TIMER_INFINITE
) {
320 ts
.tv_sec
= timer
/ 1000;
321 ts
.tv_nsec
= (timer
% 1000) * 1000000;
325 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
326 "rtsig timer: %M", timer
);
328 /* Linux's sigwaitinfo() is sigtimedwait() with the NULL timeout pointer */
330 signo
= sigtimedwait(&set
, &si
, tp
);
335 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, cycle
->log
, err
,
336 "rtsig signo:%d", signo
);
338 if (flags
& NGX_UPDATE_TIME
) {
342 if (err
== NGX_EAGAIN
) {
346 if (timer
!= NGX_TIMER_INFINITE
) {
350 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, err
,
351 "sigtimedwait() returned EAGAIN without timeout");
355 ngx_log_error((err
== NGX_EINTR
) ? NGX_LOG_INFO
: NGX_LOG_ALERT
,
356 cycle
->log
, err
, "sigtimedwait() failed");
360 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
361 "rtsig signo:%d fd:%d band:%04Xd",
362 signo
, si
.si_fd
, si
.si_band
);
364 if (flags
& NGX_UPDATE_TIME
) {
368 rtscf
= ngx_event_get_conf(ngx_cycle
->conf_ctx
, ngx_rtsig_module
);
370 if (signo
== (int) rtscf
->signo
|| signo
== (int) rtscf
->signo
+ 1) {
372 if (overflow
&& (ngx_uint_t
) si
.si_fd
> overflow_current
) {
376 c
= ngx_cycle
->files
[si
.si_fd
];
380 /* the stale event */
385 instance
= signo
- (int) rtscf
->signo
;
389 if (rev
->instance
!= instance
) {
392 * the stale event from a file descriptor
393 * that was just closed in this iteration
396 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
397 "rtsig: stale event %p", c
);
402 if ((si
.si_band
& (POLLIN
|POLLHUP
|POLLERR
)) && rev
->active
) {
406 if (flags
& NGX_POST_EVENTS
) {
407 queue
= (ngx_event_t
**) (rev
->accept
?
408 &ngx_posted_accept_events
: &ngx_posted_events
);
410 ngx_locked_post_event(rev
, queue
);
419 if ((si
.si_band
& (POLLOUT
|POLLHUP
|POLLERR
)) && wev
->active
) {
423 if (flags
& NGX_POST_EVENTS
) {
424 ngx_locked_post_event(wev
, &ngx_posted_events
);
433 } else if (signo
== SIGALRM
) {
439 } else if (signo
== SIGIO
) {
441 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0,
442 "rt signal queue overflowed");
444 /* flush the RT signal queue */
446 ngx_memzero(&sa
, sizeof(struct sigaction
));
447 sa
.sa_handler
= SIG_DFL
;
448 sigemptyset(&sa
.sa_mask
);
450 if (sigaction(rtscf
->signo
, &sa
, NULL
) == -1) {
451 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, ngx_errno
,
452 "sigaction(%d, SIG_DFL) failed", rtscf
->signo
);
455 if (sigaction(rtscf
->signo
+ 1, &sa
, NULL
) == -1) {
456 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, ngx_errno
,
457 "sigaction(%d, SIG_DFL) failed", rtscf
->signo
+ 1);
461 overflow_current
= 0;
462 ngx_event_actions
.process_events
= ngx_rtsig_process_overflow
;
468 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0,
469 "sigtimedwait() returned unexpected signal: %d", signo
);
476 ngx_rtsig_process_overflow(ngx_cycle_t
*cycle
, ngx_msec_t timer
,
479 int name
[2], rtsig_max
, rtsig_nr
, events
, ready
;
482 ngx_uint_t tested
, n
, i
;
483 ngx_event_t
*rev
, *wev
, **queue
;
485 ngx_rtsig_conf_t
*rtscf
;
487 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
488 "rtsig process overflow");
490 rtscf
= ngx_event_get_conf(ngx_cycle
->conf_ctx
, ngx_rtsig_module
);
497 while (n
< rtscf
->overflow_events
) {
499 if (overflow_current
== cycle
->connection_n
) {
503 c
= cycle
->files
[overflow_current
++];
505 if (c
== NULL
|| c
->fd
== -1) {
511 if (c
->read
->active
&& c
->read
->handler
) {
515 if (c
->write
->active
&& c
->write
->handler
) {
523 overflow_list
[n
].fd
= c
->fd
;
524 overflow_list
[n
].events
= events
;
525 overflow_list
[n
].revents
= 0;
534 ready
= poll(overflow_list
, n
, 0);
536 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
537 "rtsig overflow poll:%d", ready
);
541 ngx_log_error((err
== NGX_EINTR
) ? NGX_LOG_INFO
: NGX_LOG_ALERT
,
543 "poll() failed while the overflow recover");
545 if (err
== NGX_EINTR
) {
557 ngx_mutex_lock(ngx_posted_events_mutex
);
559 for (i
= 0; i
< n
; i
++) {
560 c
= cycle
->files
[overflow_list
[i
].fd
];
571 && (overflow_list
[i
].revents
572 & (POLLIN
|POLLERR
|POLLHUP
|POLLNVAL
)))
576 if ((flags
& NGX_POST_THREAD_EVENTS
) && !rev
->accept
) {
577 rev
->posted_ready
= 1;
583 if (flags
& NGX_POST_EVENTS
) {
584 queue
= (ngx_event_t
**) (rev
->accept
?
585 &ngx_posted_accept_events
: &ngx_posted_events
);
587 ngx_locked_post_event(rev
, queue
);
599 && (overflow_list
[i
].revents
600 & (POLLOUT
|POLLERR
|POLLHUP
|POLLNVAL
)))
604 if (flags
& NGX_POST_THREAD_EVENTS
) {
605 wev
->posted_ready
= 1;
611 if (flags
& NGX_POST_EVENTS
) {
612 ngx_locked_post_event(wev
, &ngx_posted_events
);
620 ngx_mutex_unlock(ngx_posted_events_mutex
);
622 if (tested
>= rtscf
->overflow_test
) {
624 if (ngx_linux_rtsig_max
) {
627 * Check the current rt queue length to prevent
630 * learn the "/proc/sys/kernel/rtsig-max" value because
631 * it can be changed since the last checking
635 name
[1] = KERN_RTSIGMAX
;
636 len
= sizeof(rtsig_max
);
638 if (sysctl(name
, 2, &rtsig_max
, &len
, NULL
, 0) == -1) {
639 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, errno
,
640 "sysctl(KERN_RTSIGMAX) failed");
644 /* name[0] = CTL_KERN; */
645 name
[1] = KERN_RTSIGNR
;
646 len
= sizeof(rtsig_nr
);
648 if (sysctl(name
, 2, &rtsig_nr
, &len
, NULL
, 0) == -1) {
649 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, errno
,
650 "sysctl(KERN_RTSIGNR) failed");
655 * drain the rt signal queue if the /"proc/sys/kernel/rtsig-nr"
657 * "/proc/sys/kernel/rtsig-max" / "rtsig_overflow_threshold"
660 if (rtsig_max
/ (int) rtscf
->overflow_threshold
< rtsig_nr
) {
661 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
662 "rtsig queue state: %d/%d",
663 rtsig_nr
, rtsig_max
);
664 while (ngx_rtsig_process_events(cycle
, 0, flags
) == NGX_OK
)
673 * Linux has not KERN_RTSIGMAX since 2.6.6-mm2
674 * so drain the rt signal queue unconditionally
677 while (ngx_rtsig_process_events(cycle
, 0, flags
) == NGX_OK
) {
686 if (flags
& NGX_UPDATE_TIME
) {
690 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, 0,
691 "rt signal queue overflow recovered");
694 ngx_event_actions
.process_events
= ngx_rtsig_process_events
;
701 ngx_rtsig_create_conf(ngx_cycle_t
*cycle
)
703 ngx_rtsig_conf_t
*rtscf
;
705 rtscf
= ngx_palloc(cycle
->pool
, sizeof(ngx_rtsig_conf_t
));
710 rtscf
->signo
= NGX_CONF_UNSET
;
711 rtscf
->overflow_events
= NGX_CONF_UNSET
;
712 rtscf
->overflow_test
= NGX_CONF_UNSET
;
713 rtscf
->overflow_threshold
= NGX_CONF_UNSET
;
720 ngx_rtsig_init_conf(ngx_cycle_t
*cycle
, void *conf
)
722 ngx_rtsig_conf_t
*rtscf
= conf
;
724 /* LinuxThreads use the first 3 RT signals */
725 ngx_conf_init_uint_value(rtscf
->signo
, SIGRTMIN
+ 10);
727 ngx_conf_init_uint_value(rtscf
->overflow_events
, 16);
728 ngx_conf_init_uint_value(rtscf
->overflow_test
, 32);
729 ngx_conf_init_uint_value(rtscf
->overflow_threshold
, 10);
736 ngx_check_ngx_overflow_threshold_bounds(ngx_conf_t
*cf
, void *post
, void *data
)
738 if (ngx_linux_rtsig_max
) {
739 return ngx_conf_check_num_bounds(cf
, post
, data
);
742 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
743 "\"rtsig_overflow_threshold\" is not supported "
744 "since Linux 2.6.6-mm2, ignored");