blob: 5d957ecffe0a9cff056232a818c4b152fbfec04a [file] [log] [blame]
Igor Sysoev9139cd22004-02-17 17:53:12 +00001
2/*
3 * Copyright (C) 2002-2004 Igor Sysoev, http://sysoev.ru/en/
4 */
5
6
7#include <ngx_config.h>
8#include <ngx_core.h>
9#include <ngx_event.h>
10
11
12#if (TEST_BUILD_RTSIG)
13
Igor Sysoevebfd6c82004-06-09 07:45:27 +000014#define F_SETSIG 10
15#define SIGRTMIN 33
16#define si_fd __spare__[0]
17#define KERN_RTSIGNR 30
18#define KERN_RTSIGMAX 31
Igor Sysoev9139cd22004-02-17 17:53:12 +000019
Igor Sysoev9139cd22004-02-17 17:53:12 +000020int sigtimedwait(const sigset_t *set, siginfo_t *info,
Igor Sysoev9139cd22004-02-17 17:53:12 +000021 const struct timespec *timeout)
22{
23 return -1;
24}
25
26#endif
27
28
29typedef struct {
Igor Sysoev0ed19cc2004-06-10 18:36:57 +000030 int signo;
31 ngx_int_t overflow_events;
32 ngx_int_t overflow_test;
33 ngx_int_t overflow_threshold;
Igor Sysoev9139cd22004-02-17 17:53:12 +000034} ngx_rtsig_conf_t;
35
36
Igor Sysoev22a7c502004-02-17 21:11:27 +000037extern ngx_event_module_t ngx_poll_module_ctx;
38
Igor Sysoevebfd6c82004-06-09 07:45:27 +000039static ngx_int_t ngx_rtsig_init(ngx_cycle_t *cycle);
Igor Sysoev9139cd22004-02-17 17:53:12 +000040static void ngx_rtsig_done(ngx_cycle_t *cycle);
Igor Sysoevebfd6c82004-06-09 07:45:27 +000041static ngx_int_t ngx_rtsig_add_connection(ngx_connection_t *c);
42static ngx_int_t ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags);
43static ngx_int_t ngx_rtsig_process_events(ngx_cycle_t *cycle);
44static ngx_int_t ngx_rtsig_process_overflow(ngx_cycle_t *cycle);
Igor Sysoev9139cd22004-02-17 17:53:12 +000045
46static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle);
47static char *ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf);
48
49
Igor Sysoev0ed19cc2004-06-10 18:36:57 +000050static sigset_t set;
51static ngx_uint_t overflow, overflow_current;
52static struct pollfd *overflow_list;
Igor Sysoev9139cd22004-02-17 17:53:12 +000053
54
55static ngx_str_t rtsig_name = ngx_string("rtsig");
56
Igor Sysoev0ed19cc2004-06-10 18:36:57 +000057static ngx_conf_num_bounds_t ngx_overflow_threshold_bounds = {
58 ngx_conf_check_num_bounds, 2, 10
59};
60
61
Igor Sysoev9139cd22004-02-17 17:53:12 +000062static ngx_command_t ngx_rtsig_commands[] = {
63
64 {ngx_string("rtsig_signo"),
65 NGX_EVENT_CONF|NGX_CONF_TAKE1,
66 ngx_conf_set_num_slot,
67 0,
68 offsetof(ngx_rtsig_conf_t, signo),
69 NULL},
70
Igor Sysoev0ed19cc2004-06-10 18:36:57 +000071 {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},
91
Igor Sysoev9139cd22004-02-17 17:53:12 +000092 ngx_null_command
93};
94
95
96ngx_event_module_t ngx_rtsig_module_ctx = {
97 &rtsig_name,
98 ngx_rtsig_create_conf, /* create configuration */
99 ngx_rtsig_init_conf, /* init configuration */
100
101 {
102 NULL, /* add an event */
103 NULL, /* delete an event */
104 NULL, /* enable an event */
105 NULL, /* disable an event */
106 ngx_rtsig_add_connection, /* add an connection */
107 ngx_rtsig_del_connection, /* delete an connection */
108 ngx_rtsig_process_events, /* process the events */
109 ngx_rtsig_init, /* init the events */
110 ngx_rtsig_done, /* done the events */
111 }
112
113};
114
115ngx_module_t ngx_rtsig_module = {
116 NGX_MODULE,
117 &ngx_rtsig_module_ctx, /* module context */
118 ngx_rtsig_commands, /* module directives */
119 NGX_EVENT_MODULE, /* module type */
120 NULL, /* init module */
121 NULL /* init child */
122};
123
124
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000125static ngx_int_t ngx_rtsig_init(ngx_cycle_t *cycle)
Igor Sysoev9139cd22004-02-17 17:53:12 +0000126{
127 ngx_rtsig_conf_t *rtscf;
128
Igor Sysoev22a7c502004-02-17 21:11:27 +0000129 if (ngx_poll_module_ctx.actions.init(cycle) == NGX_ERROR) {
130 return NGX_ERROR;
131 }
132
Igor Sysoev9139cd22004-02-17 17:53:12 +0000133 rtscf = ngx_event_get_conf(cycle->conf_ctx, ngx_rtsig_module);
134
135 sigemptyset(&set);
136 sigaddset(&set, rtscf->signo);
Igor Sysoev67f450d2004-06-01 06:04:46 +0000137 sigaddset(&set, rtscf->signo + 1);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000138 sigaddset(&set, SIGIO);
139
140 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
141 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
142 "sigprocmask() failed");
143 return NGX_ERROR;
144 }
145
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000146 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) {
153 return NGX_ERROR;
154 }
155
Igor Sysoev9139cd22004-02-17 17:53:12 +0000156 ngx_io = ngx_os_io;
157
158 ngx_event_actions = ngx_rtsig_module_ctx.actions;
159
Igor Sysoev0ab91b92004-06-06 19:49:18 +0000160 ngx_event_flags = NGX_USE_RTSIG_EVENT
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000161 |NGX_HAVE_GREEDY_EVENT
162 |NGX_HAVE_INSTANCE_EVENT;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000163
164 return NGX_OK;
165}
166
167
168static void ngx_rtsig_done(ngx_cycle_t *cycle)
169{
Igor Sysoev22a7c502004-02-17 21:11:27 +0000170 ngx_poll_module_ctx.actions.done(cycle);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000171}
172
173
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000174static ngx_int_t ngx_rtsig_add_connection(ngx_connection_t *c)
Igor Sysoev9139cd22004-02-17 17:53:12 +0000175{
Igor Sysoev67f450d2004-06-01 06:04:46 +0000176 int signo;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000177 ngx_rtsig_conf_t *rtscf;
178
Igor Sysoev956ae652004-06-09 16:36:55 +0000179 if (c->read->accept && c->read->disabled) {
180 if (fcntl(c->fd, F_SETOWN, ngx_pid) == -1) {
181 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
182 "fcntl(F_SETOWN) failed");
183 return NGX_ERROR;
184 }
185
186 c->read->active = 1;
187 c->read->disabled = 0;
188 }
189
Igor Sysoev9139cd22004-02-17 17:53:12 +0000190 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
191
Igor Sysoev67f450d2004-06-01 06:04:46 +0000192 signo = rtscf->signo + c->read->instance;
193
Igor Sysoev9139cd22004-02-17 17:53:12 +0000194 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
Igor Sysoev67f450d2004-06-01 06:04:46 +0000195 "rtsig add connection: fd:%d signo:%d", c->fd, signo);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000196
197 if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) == -1) {
198 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
199 "fcntl(O_RDWR|O_NONBLOCK|O_ASYNC) failed");
200 return NGX_ERROR;
201 }
202
Igor Sysoev67f450d2004-06-01 06:04:46 +0000203 if (fcntl(c->fd, F_SETSIG, signo) == -1) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000204 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
205 "fcntl(F_SETSIG) failed");
206 return NGX_ERROR;
207 }
208
Igor Sysoev67f450d2004-06-01 06:04:46 +0000209 if (fcntl(c->fd, F_SETOWN, ngx_pid) == -1) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000210 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
211 "fcntl(F_SETOWN) failed");
212 return NGX_ERROR;
213 }
214
215#if (HAVE_ONESIGFD)
216 if (fcntl(c->fd, F_SETAUXFL, O_ONESIGFD) == -1) {
217 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
218 "fcntl(F_SETAUXFL) failed");
219 return NGX_ERROR;
220 }
221#endif
222
223 c->read->active = 1;
224 c->write->active = 1;
225
226 return NGX_OK;
227}
228
229
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000230static ngx_int_t ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags)
Igor Sysoev9139cd22004-02-17 17:53:12 +0000231{
Igor Sysoev67f450d2004-06-01 06:04:46 +0000232 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
233 "rtsig del connection: fd:%d", c->fd);
234
Igor Sysoev956ae652004-06-09 16:36:55 +0000235 if ((flags & NGX_DISABLE_EVENT) && c->read->accept) {
236 c->read->active = 0;
237 c->read->disabled = 0;
238 return NGX_OK;
239 }
240
241 if (flags & NGX_CLOSE_EVENT) {
242 c->read->active = 0;
243 c->write->active = 0;
244 return NGX_OK;
245 }
246
247 if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK) == -1) {
248 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
249 "fcntl(O_RDWR|O_NONBLOCK) failed");
250 return NGX_ERROR;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000251 }
252
Igor Sysoev9139cd22004-02-17 17:53:12 +0000253 c->read->active = 0;
254 c->write->active = 0;
255
256 return NGX_OK;
257}
258
259
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000260ngx_int_t ngx_rtsig_process_events(ngx_cycle_t *cycle)
Igor Sysoev9139cd22004-02-17 17:53:12 +0000261{
262 int signo;
263 ngx_int_t instance, i;
Igor Sysoevcccc5522004-04-14 20:34:05 +0000264 ngx_uint_t expire;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000265 size_t n;
266 ngx_msec_t timer;
267 ngx_err_t err;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000268 siginfo_t si;
269 struct timeval tv;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000270 struct timespec ts, *tp;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000271 struct sigaction sa;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000272 ngx_epoch_msec_t delta;
Igor Sysoevcccc5522004-04-14 20:34:05 +0000273 ngx_connection_t *c;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000274 ngx_rtsig_conf_t *rtscf;
275
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000276 if (overflow) {
277 timer = 0;
278 expire = 0;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000279
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000280 } else {
281 for ( ;; ) {
282 timer = ngx_event_find_timer();
Igor Sysoevcccc5522004-04-14 20:34:05 +0000283
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000284 if (timer != 0) {
285 break;
Igor Sysoev732a2712004-04-21 18:54:33 +0000286 }
287
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000288 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
289 "rtsig expired timer");
290
291 ngx_event_expire_timers((ngx_msec_t)
292 (ngx_elapsed_msec - ngx_old_elapsed_msec));
293 }
294
295 expire = 1;
296
297 if (ngx_accept_mutex) {
298 if (ngx_accept_disabled > 0) {
299 ngx_accept_disabled--;
300
301 } else {
302 if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
303 return NGX_ERROR;
304 }
305
306 if (ngx_accept_mutex_held == 0
307 && (timer == NGX_TIMER_INFINITE
308 || timer > ngx_accept_mutex_delay))
309 {
310 timer = ngx_accept_mutex_delay;
311 expire = 0;
312 }
313 }
Igor Sysoevcccc5522004-04-14 20:34:05 +0000314 }
315 }
316
317 if (timer == NGX_TIMER_INFINITE) {
318 tp = NULL;
319 expire = 0;
320
321 } else {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000322 ts.tv_sec = timer / 1000;
323 ts.tv_nsec = (timer % 1000) * 1000000;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000324 tp = &ts;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000325 }
326
Igor Sysoevcccc5522004-04-14 20:34:05 +0000327 ngx_old_elapsed_msec = ngx_elapsed_msec;
328
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000329 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
330 "rtsig timer: %d", timer);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000331
Igor Sysoev22a7c502004-02-17 21:11:27 +0000332 /* Linux sigwaitinfo() is sigtimedwait() with the NULL timeout pointer */
333
334 signo = sigtimedwait(&set, &si, tp);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000335
336 if (signo == -1) {
337 err = ngx_errno;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000338
339 if (err == NGX_EAGAIN) {
340
341 if (timer == NGX_TIMER_INFINITE) {
342 ngx_accept_mutex_unlock();
343 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
344 "sigtimedwait() returned EAGAIN without timeout");
345 return NGX_ERROR;
346 }
347
348 err = 0;
349 }
350
Igor Sysoev9139cd22004-02-17 17:53:12 +0000351 } else {
352 err = 0;
353 }
354
355 ngx_gettimeofday(&tv);
356 ngx_time_update(tv.tv_sec);
357
358 delta = ngx_elapsed_msec;
359 ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
360
Igor Sysoev22a7c502004-02-17 21:11:27 +0000361 if (err) {
Igor Sysoev67f450d2004-06-01 06:04:46 +0000362 ngx_accept_mutex_unlock();
Igor Sysoev9139cd22004-02-17 17:53:12 +0000363 ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000364 cycle->log, err, "sigtimedwait() failed");
Igor Sysoev9139cd22004-02-17 17:53:12 +0000365 return NGX_ERROR;
366 }
367
Igor Sysoevcccc5522004-04-14 20:34:05 +0000368 if (timer != NGX_TIMER_INFINITE) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000369 delta = ngx_elapsed_msec - delta;
370
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000371 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
Igor Sysoev9139cd22004-02-17 17:53:12 +0000372 "rtsig timer: %d, delta: %d", timer, (int) delta);
373 }
374
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000375 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
Igor Sysoev67f450d2004-06-01 06:04:46 +0000376 "rtsig signo:%d fd:%d band:%X", signo, si.si_fd, si.si_band);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000377
378 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
379
Igor Sysoev67f450d2004-06-01 06:04:46 +0000380 if (signo == rtscf->signo || signo == rtscf->signo + 1) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000381
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000382 if (overflow && (ngx_uint_t) si.si_fd > overflow_current) {
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000383 return NGX_OK;
384 }
385
Igor Sysoev9139cd22004-02-17 17:53:12 +0000386 /* TODO: old_cycles */
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000387
Igor Sysoev9139cd22004-02-17 17:53:12 +0000388 c = &ngx_cycle->connections[si.si_fd];
389
Igor Sysoev67f450d2004-06-01 06:04:46 +0000390 instance = signo - rtscf->signo;
391
392 if (si.si_band & POLLIN) {
393 c->read->returned_instance = instance;
394 }
395
396 if (si.si_band & POLLOUT) {
397 c->write->returned_instance = instance;
398 }
399
400 if (c->read->instance != instance) {
401
402 /*
403 * the stale event from a file descriptor
404 * that was just closed in this iteration
405 */
406
407 ngx_accept_mutex_unlock();
408
409 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
410 "rtsig: stale event " PTR_FMT, c);
411
412 return NGX_OK;
413 }
Igor Sysoev9139cd22004-02-17 17:53:12 +0000414
415 if (si.si_band & (POLLIN|POLLHUP|POLLERR)) {
416 if (c->read->active) {
417 c->read->ready = 1;
Igor Sysoevcccc5522004-04-14 20:34:05 +0000418
419 if (!ngx_threaded && !ngx_accept_mutex_held) {
420 c->read->event_handler(c->read);
421
422 } else if (c->read->accept) {
Igor Sysoev67f450d2004-06-01 06:04:46 +0000423 if (ngx_accept_disabled <= 0) {
Igor Sysoev732a2712004-04-21 18:54:33 +0000424 c->read->event_handler(c->read);
425 }
Igor Sysoevcccc5522004-04-14 20:34:05 +0000426
427 } else {
428 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
429 ngx_accept_mutex_unlock();
430 return NGX_ERROR;
431 }
432
433 ngx_post_event(c->read);
434
435 ngx_mutex_unlock(ngx_posted_events_mutex);
436 }
Igor Sysoev9139cd22004-02-17 17:53:12 +0000437 }
438 }
439
440 if (si.si_band & (POLLOUT|POLLHUP|POLLERR)) {
441 if (c->write->active) {
442 c->write->ready = 1;
Igor Sysoevcccc5522004-04-14 20:34:05 +0000443
444 if (!ngx_threaded && !ngx_accept_mutex_held) {
445 c->write->event_handler(c->write);
446
447 } else {
448
449 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
450 ngx_accept_mutex_unlock();
451 return NGX_ERROR;
452 }
453
454 ngx_post_event(c->write);
455
456 ngx_mutex_unlock(ngx_posted_events_mutex);
457 }
Igor Sysoev9139cd22004-02-17 17:53:12 +0000458 }
459 }
460
461 } else if (signo == SIGIO) {
Igor Sysoevcccc5522004-04-14 20:34:05 +0000462 ngx_accept_mutex_unlock();
463
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000464 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
465 "rt signal queue overflowed");
Igor Sysoev9139cd22004-02-17 17:53:12 +0000466
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000467 /* flush the RT signal queue */
Igor Sysoev22a7c502004-02-17 21:11:27 +0000468
Igor Sysoev9139cd22004-02-17 17:53:12 +0000469 ngx_memzero(&sa, sizeof(struct sigaction));
470 sa.sa_handler = SIG_DFL;
471 sigemptyset(&sa.sa_mask);
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000472
Igor Sysoev9139cd22004-02-17 17:53:12 +0000473 if (sigaction(rtscf->signo, &sa, NULL) == -1) {
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000474 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
Igor Sysoev9139cd22004-02-17 17:53:12 +0000475 "sigaction(%d, SIG_DFL) failed", rtscf->signo);
476 }
477
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000478 if (sigaction(rtscf->signo + 1, &sa, NULL) == -1) {
479 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
480 "sigaction(%d, SIG_DFL) failed", rtscf->signo + 1);
481 }
482
483 overflow = 1;
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000484 overflow_current = 0;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000485 ngx_event_actions.process = ngx_rtsig_process_overflow;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000486
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000487 return NGX_OK;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000488
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000489 } else if (signo != -1) {
Igor Sysoev67f450d2004-06-01 06:04:46 +0000490 ngx_accept_mutex_unlock();
491
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000492 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
Igor Sysoev22a7c502004-02-17 21:11:27 +0000493 "sigtimedwait() returned unexpected signal: %d", signo);
Igor Sysoev67f450d2004-06-01 06:04:46 +0000494
Igor Sysoev9139cd22004-02-17 17:53:12 +0000495 return NGX_ERROR;
496 }
497
Igor Sysoevcccc5522004-04-14 20:34:05 +0000498 ngx_accept_mutex_unlock();
499
500 if (expire && delta) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000501 ngx_event_expire_timers((ngx_msec_t) delta);
502 }
503
Igor Sysoevcccc5522004-04-14 20:34:05 +0000504 if (!ngx_threaded) {
505 ngx_event_process_posted(cycle);
506 }
507
Igor Sysoev956ae652004-06-09 16:36:55 +0000508 if (signo == -1) {
509 return NGX_AGAIN;
510 } else {
511 return NGX_OK;
512 }
Igor Sysoev9139cd22004-02-17 17:53:12 +0000513}
514
515
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000516/* TODO: old cylces */
517
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000518static ngx_int_t ngx_rtsig_process_overflow(ngx_cycle_t *cycle)
Igor Sysoev22a7c502004-02-17 21:11:27 +0000519{
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000520 int name[2], len, rtsig_max, rtsig_nr, events, ready;
521 ngx_int_t tested, n, i;
522 ngx_err_t err;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000523 ngx_connection_t *c;
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000524 ngx_rtsig_conf_t *rtscf;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000525
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000526 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000527
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000528 tested = 0;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000529
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000530 for ( ;; ) {
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000531
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000532 n = 0;
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) {
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000587 continue;
588 }
589
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000590 for (i = 0; i < n; i++) {
591 c = &cycle->connections[overflow_list[i].fd];
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000592
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000593 if (overflow_list[i].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) {
594 tested++;
595 c->read->ready = 1;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000596
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000597 if (!ngx_threaded) {
598 c->read->event_handler(c->read);
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);
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000609 }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000610 }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000611
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000612 if (overflow_list[i].revents & (POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
613 tested++;
614 c->write->ready = 1;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000615
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000616 if (!ngx_threaded) {
617 c->write->event_handler(c->write);
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000618
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000619 } else {
620 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
621 return NGX_ERROR;
622 }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000623
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000624 ngx_post_event(c->write);
625 c->write->returned_instance = c->write->instance;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000626
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000627 ngx_mutex_unlock(ngx_posted_events_mutex);
628 }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000629 }
630 }
631
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000632 if (tested >= rtscf->overflow_test) {
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000633
634 /*
635 * Check the current rt queue length to prevent the new overflow.
636 *
637 * Learn the /proc/sys/kernel/rtsig-max value because
Igor Sysoev5428ae72004-06-09 20:03:54 +0000638 * it can be changed sisnce the last checking.
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000639 */
640
641 name[0] = CTL_KERN;
642 name[1] = KERN_RTSIGMAX;
643 len = sizeof(rtsig_max);
644 if (sysctl(name, sizeof(name), &rtsig_max, &len, NULL, 0) == -1) {
645 ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
646 "sysctl(KERN_RTSIGMAX) failed");
647 return NGX_ERROR;
648 }
649
650 name[0] = CTL_KERN;
651 name[1] = KERN_RTSIGNR;
652 len = sizeof(rtsig_nr);
653 if (sysctl(name, sizeof(name), &rtsig_nr, &len, NULL, 0) == -1) {
654 ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
655 "sysctl(KERN_RTSIGNR) failed");
656 return NGX_ERROR;
657 }
658
659 /*
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000660 * drain rt signal queue if the /proc/sys/kernel/rtsig-nr is bigger
661 * than "/proc/sys/kernel/rtsig-max / rtsig_overflow_threshold"
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000662 */
663
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000664 if (rtsig_max / rtscf->overflow_threshold < rtsig_nr) {
Igor Sysoev5428ae72004-06-09 20:03:54 +0000665 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
666 "rtsig queue state: %d/%d", rtsig_nr, rtsig_max);
Igor Sysoev956ae652004-06-09 16:36:55 +0000667 while (ngx_rtsig_process_events(cycle) == NGX_OK) { /* void */ }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000668 }
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000669
670 tested = 0;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000671 }
Igor Sysoev22a7c502004-02-17 21:11:27 +0000672 }
673
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000674 if (!ngx_threaded) {
675 ngx_event_process_posted(cycle);
676 }
677
678 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
679 "rt signal queue overflow recovered");
680
681 overflow = 0;
682 ngx_event_actions.process = ngx_rtsig_process_events;
683
Igor Sysoev22a7c502004-02-17 21:11:27 +0000684 return NGX_OK;
685}
686
687
Igor Sysoev9139cd22004-02-17 17:53:12 +0000688static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle)
689{
690 ngx_rtsig_conf_t *rtscf;
691
692 ngx_test_null(rtscf, ngx_palloc(cycle->pool, sizeof(ngx_rtsig_conf_t)),
693 NGX_CONF_ERROR);
694
695 rtscf->signo = NGX_CONF_UNSET;
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000696 rtscf->overflow_events = NGX_CONF_UNSET;
697 rtscf->overflow_test = NGX_CONF_UNSET;
698 rtscf->overflow_threshold = NGX_CONF_UNSET;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000699
700 return rtscf;
701}
702
703
704static char *ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf)
705{
706 ngx_rtsig_conf_t *rtscf = conf;
707
708 /* LinuxThreads use the first 3 RT signals */
709 ngx_conf_init_value(rtscf->signo, SIGRTMIN + 10);
710
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000711 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
Igor Sysoev9139cd22004-02-17 17:53:12 +0000715 return NGX_CONF_OK;
716}