blob: d0e7fee7de4b1d27b2fb5771a47823a444fb0416 [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 */
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000108 NULL, /* process the changes */
Igor Sysoev9139cd22004-02-17 17:53:12 +0000109 ngx_rtsig_process_events, /* process the events */
110 ngx_rtsig_init, /* init the events */
111 ngx_rtsig_done, /* done the events */
112 }
113
114};
115
116ngx_module_t ngx_rtsig_module = {
117 NGX_MODULE,
118 &ngx_rtsig_module_ctx, /* module context */
119 ngx_rtsig_commands, /* module directives */
120 NGX_EVENT_MODULE, /* module type */
121 NULL, /* init module */
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000122 NULL /* init process */
Igor Sysoev9139cd22004-02-17 17:53:12 +0000123};
124
125
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000126static ngx_int_t ngx_rtsig_init(ngx_cycle_t *cycle)
Igor Sysoev9139cd22004-02-17 17:53:12 +0000127{
128 ngx_rtsig_conf_t *rtscf;
129
Igor Sysoev22a7c502004-02-17 21:11:27 +0000130 if (ngx_poll_module_ctx.actions.init(cycle) == NGX_ERROR) {
131 return NGX_ERROR;
132 }
133
Igor Sysoev9139cd22004-02-17 17:53:12 +0000134 rtscf = ngx_event_get_conf(cycle->conf_ctx, ngx_rtsig_module);
135
136 sigemptyset(&set);
137 sigaddset(&set, rtscf->signo);
Igor Sysoev67f450d2004-06-01 06:04:46 +0000138 sigaddset(&set, rtscf->signo + 1);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000139 sigaddset(&set, SIGIO);
140
141 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
142 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
143 "sigprocmask() failed");
144 return NGX_ERROR;
145 }
146
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000147 if (overflow_list) {
148 ngx_free(overflow_list);
149 }
150
151 overflow_list = ngx_alloc(sizeof(struct pollfd) * rtscf->overflow_events,
152 cycle->log);
153 if (overflow_list == NULL) {
154 return NGX_ERROR;
155 }
156
Igor Sysoev9139cd22004-02-17 17:53:12 +0000157 ngx_io = ngx_os_io;
158
159 ngx_event_actions = ngx_rtsig_module_ctx.actions;
160
Igor Sysoev0ab91b92004-06-06 19:49:18 +0000161 ngx_event_flags = NGX_USE_RTSIG_EVENT
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000162 |NGX_HAVE_GREEDY_EVENT
163 |NGX_HAVE_INSTANCE_EVENT;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000164
165 return NGX_OK;
166}
167
168
169static void ngx_rtsig_done(ngx_cycle_t *cycle)
170{
Igor Sysoev22a7c502004-02-17 21:11:27 +0000171 ngx_poll_module_ctx.actions.done(cycle);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000172}
173
174
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000175static ngx_int_t ngx_rtsig_add_connection(ngx_connection_t *c)
Igor Sysoev9139cd22004-02-17 17:53:12 +0000176{
Igor Sysoev67f450d2004-06-01 06:04:46 +0000177 int signo;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000178 ngx_rtsig_conf_t *rtscf;
179
Igor Sysoev956ae652004-06-09 16:36:55 +0000180 if (c->read->accept && c->read->disabled) {
Igor Sysoev87350f22004-06-15 07:55:11 +0000181
182 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
183 "rtsig enable connection: fd:%d", c->fd);
184
Igor Sysoev956ae652004-06-09 16:36:55 +0000185 if (fcntl(c->fd, F_SETOWN, ngx_pid) == -1) {
186 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
187 "fcntl(F_SETOWN) failed");
188 return NGX_ERROR;
189 }
190
191 c->read->active = 1;
192 c->read->disabled = 0;
193 }
194
Igor Sysoev9139cd22004-02-17 17:53:12 +0000195 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
196
Igor Sysoev67f450d2004-06-01 06:04:46 +0000197 signo = rtscf->signo + c->read->instance;
198
Igor Sysoev9139cd22004-02-17 17:53:12 +0000199 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
Igor Sysoev67f450d2004-06-01 06:04:46 +0000200 "rtsig add connection: fd:%d signo:%d", c->fd, signo);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000201
202 if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) == -1) {
203 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
204 "fcntl(O_RDWR|O_NONBLOCK|O_ASYNC) failed");
205 return NGX_ERROR;
206 }
207
Igor Sysoev67f450d2004-06-01 06:04:46 +0000208 if (fcntl(c->fd, F_SETSIG, signo) == -1) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000209 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
210 "fcntl(F_SETSIG) failed");
211 return NGX_ERROR;
212 }
213
Igor Sysoev67f450d2004-06-01 06:04:46 +0000214 if (fcntl(c->fd, F_SETOWN, ngx_pid) == -1) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000215 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
216 "fcntl(F_SETOWN) failed");
217 return NGX_ERROR;
218 }
219
220#if (HAVE_ONESIGFD)
221 if (fcntl(c->fd, F_SETAUXFL, O_ONESIGFD) == -1) {
222 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
223 "fcntl(F_SETAUXFL) failed");
224 return NGX_ERROR;
225 }
226#endif
227
228 c->read->active = 1;
229 c->write->active = 1;
230
231 return NGX_OK;
232}
233
234
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000235static ngx_int_t ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags)
Igor Sysoev9139cd22004-02-17 17:53:12 +0000236{
Igor Sysoev67f450d2004-06-01 06:04:46 +0000237 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
238 "rtsig del connection: fd:%d", c->fd);
239
Igor Sysoev956ae652004-06-09 16:36:55 +0000240 if ((flags & NGX_DISABLE_EVENT) && c->read->accept) {
Igor Sysoev87350f22004-06-15 07:55:11 +0000241
242 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
243 "rtsig disable connection: fd:%d", c->fd);
244
Igor Sysoev956ae652004-06-09 16:36:55 +0000245 c->read->active = 0;
Igor Sysoev87350f22004-06-15 07:55:11 +0000246 c->read->disabled = 1;
Igor Sysoev956ae652004-06-09 16:36:55 +0000247 return NGX_OK;
248 }
249
250 if (flags & NGX_CLOSE_EVENT) {
251 c->read->active = 0;
252 c->write->active = 0;
253 return NGX_OK;
254 }
255
256 if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK) == -1) {
257 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
258 "fcntl(O_RDWR|O_NONBLOCK) failed");
259 return NGX_ERROR;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000260 }
261
Igor Sysoev9139cd22004-02-17 17:53:12 +0000262 c->read->active = 0;
263 c->write->active = 0;
264
265 return NGX_OK;
266}
267
268
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000269ngx_int_t ngx_rtsig_process_events(ngx_cycle_t *cycle)
Igor Sysoev9139cd22004-02-17 17:53:12 +0000270{
271 int signo;
272 ngx_int_t instance, i;
Igor Sysoevcccc5522004-04-14 20:34:05 +0000273 ngx_uint_t expire;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000274 size_t n;
275 ngx_msec_t timer;
276 ngx_err_t err;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000277 siginfo_t si;
278 struct timeval tv;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000279 struct timespec ts, *tp;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000280 struct sigaction sa;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000281 ngx_epoch_msec_t delta;
Igor Sysoevcccc5522004-04-14 20:34:05 +0000282 ngx_connection_t *c;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000283 ngx_rtsig_conf_t *rtscf;
284
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000285 if (overflow) {
286 timer = 0;
287 expire = 0;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000288
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000289 } else {
290 for ( ;; ) {
291 timer = ngx_event_find_timer();
Igor Sysoevcccc5522004-04-14 20:34:05 +0000292
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000293 if (timer != 0) {
294 break;
Igor Sysoev732a2712004-04-21 18:54:33 +0000295 }
296
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000297 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
298 "rtsig expired timer");
299
300 ngx_event_expire_timers((ngx_msec_t)
301 (ngx_elapsed_msec - ngx_old_elapsed_msec));
302 }
303
304 expire = 1;
305
306 if (ngx_accept_mutex) {
307 if (ngx_accept_disabled > 0) {
308 ngx_accept_disabled--;
309
310 } else {
Igor Sysoev87350f22004-06-15 07:55:11 +0000311 ngx_accept_mutex_held = 0;
312
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000313 if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
314 return NGX_ERROR;
315 }
316
317 if (ngx_accept_mutex_held == 0
318 && (timer == NGX_TIMER_INFINITE
319 || timer > ngx_accept_mutex_delay))
320 {
321 timer = ngx_accept_mutex_delay;
322 expire = 0;
323 }
324 }
Igor Sysoevcccc5522004-04-14 20:34:05 +0000325 }
326 }
327
328 if (timer == NGX_TIMER_INFINITE) {
329 tp = NULL;
330 expire = 0;
331
332 } else {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000333 ts.tv_sec = timer / 1000;
334 ts.tv_nsec = (timer % 1000) * 1000000;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000335 tp = &ts;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000336 }
337
Igor Sysoevcccc5522004-04-14 20:34:05 +0000338 ngx_old_elapsed_msec = ngx_elapsed_msec;
339
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000340 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
341 "rtsig timer: %d", timer);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000342
Igor Sysoev22a7c502004-02-17 21:11:27 +0000343 /* Linux sigwaitinfo() is sigtimedwait() with the NULL timeout pointer */
344
345 signo = sigtimedwait(&set, &si, tp);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000346
347 if (signo == -1) {
348 err = ngx_errno;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000349
350 if (err == NGX_EAGAIN) {
351
352 if (timer == NGX_TIMER_INFINITE) {
353 ngx_accept_mutex_unlock();
354 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
355 "sigtimedwait() returned EAGAIN without timeout");
356 return NGX_ERROR;
357 }
358
359 err = 0;
360 }
361
Igor Sysoev9139cd22004-02-17 17:53:12 +0000362 } else {
363 err = 0;
364 }
365
366 ngx_gettimeofday(&tv);
367 ngx_time_update(tv.tv_sec);
368
369 delta = ngx_elapsed_msec;
370 ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
371
Igor Sysoev22a7c502004-02-17 21:11:27 +0000372 if (err) {
Igor Sysoev67f450d2004-06-01 06:04:46 +0000373 ngx_accept_mutex_unlock();
Igor Sysoev9139cd22004-02-17 17:53:12 +0000374 ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000375 cycle->log, err, "sigtimedwait() failed");
Igor Sysoev9139cd22004-02-17 17:53:12 +0000376 return NGX_ERROR;
377 }
378
Igor Sysoevcccc5522004-04-14 20:34:05 +0000379 if (timer != NGX_TIMER_INFINITE) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000380 delta = ngx_elapsed_msec - delta;
381
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000382 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
Igor Sysoev9139cd22004-02-17 17:53:12 +0000383 "rtsig timer: %d, delta: %d", timer, (int) delta);
384 }
385
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000386 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
Igor Sysoev67f450d2004-06-01 06:04:46 +0000387 "rtsig signo:%d fd:%d band:%X", signo, si.si_fd, si.si_band);
Igor Sysoev9139cd22004-02-17 17:53:12 +0000388
389 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
390
Igor Sysoev67f450d2004-06-01 06:04:46 +0000391 if (signo == rtscf->signo || signo == rtscf->signo + 1) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000392
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000393 if (overflow && (ngx_uint_t) si.si_fd > overflow_current) {
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000394 return NGX_OK;
395 }
396
Igor Sysoev9139cd22004-02-17 17:53:12 +0000397 /* TODO: old_cycles */
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000398
Igor Sysoev9139cd22004-02-17 17:53:12 +0000399 c = &ngx_cycle->connections[si.si_fd];
400
Igor Sysoev67f450d2004-06-01 06:04:46 +0000401 instance = signo - rtscf->signo;
402
403 if (si.si_band & POLLIN) {
404 c->read->returned_instance = instance;
405 }
406
407 if (si.si_band & POLLOUT) {
408 c->write->returned_instance = instance;
409 }
410
411 if (c->read->instance != instance) {
412
413 /*
414 * the stale event from a file descriptor
415 * that was just closed in this iteration
416 */
417
418 ngx_accept_mutex_unlock();
419
420 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
421 "rtsig: stale event " PTR_FMT, c);
422
423 return NGX_OK;
424 }
Igor Sysoev9139cd22004-02-17 17:53:12 +0000425
426 if (si.si_band & (POLLIN|POLLHUP|POLLERR)) {
427 if (c->read->active) {
428 c->read->ready = 1;
Igor Sysoevcccc5522004-04-14 20:34:05 +0000429
430 if (!ngx_threaded && !ngx_accept_mutex_held) {
431 c->read->event_handler(c->read);
432
433 } else if (c->read->accept) {
Igor Sysoev67f450d2004-06-01 06:04:46 +0000434 if (ngx_accept_disabled <= 0) {
Igor Sysoev732a2712004-04-21 18:54:33 +0000435 c->read->event_handler(c->read);
436 }
Igor Sysoevcccc5522004-04-14 20:34:05 +0000437
438 } else {
439 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
440 ngx_accept_mutex_unlock();
441 return NGX_ERROR;
442 }
443
444 ngx_post_event(c->read);
445
446 ngx_mutex_unlock(ngx_posted_events_mutex);
447 }
Igor Sysoev9139cd22004-02-17 17:53:12 +0000448 }
449 }
450
451 if (si.si_band & (POLLOUT|POLLHUP|POLLERR)) {
452 if (c->write->active) {
453 c->write->ready = 1;
Igor Sysoevcccc5522004-04-14 20:34:05 +0000454
455 if (!ngx_threaded && !ngx_accept_mutex_held) {
456 c->write->event_handler(c->write);
457
458 } else {
459
460 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
461 ngx_accept_mutex_unlock();
462 return NGX_ERROR;
463 }
464
465 ngx_post_event(c->write);
466
467 ngx_mutex_unlock(ngx_posted_events_mutex);
468 }
Igor Sysoev9139cd22004-02-17 17:53:12 +0000469 }
470 }
471
472 } else if (signo == SIGIO) {
Igor Sysoevcccc5522004-04-14 20:34:05 +0000473 ngx_accept_mutex_unlock();
474
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000475 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
476 "rt signal queue overflowed");
Igor Sysoev9139cd22004-02-17 17:53:12 +0000477
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000478 /* flush the RT signal queue */
Igor Sysoev22a7c502004-02-17 21:11:27 +0000479
Igor Sysoev9139cd22004-02-17 17:53:12 +0000480 ngx_memzero(&sa, sizeof(struct sigaction));
481 sa.sa_handler = SIG_DFL;
482 sigemptyset(&sa.sa_mask);
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000483
Igor Sysoev9139cd22004-02-17 17:53:12 +0000484 if (sigaction(rtscf->signo, &sa, NULL) == -1) {
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000485 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
Igor Sysoev9139cd22004-02-17 17:53:12 +0000486 "sigaction(%d, SIG_DFL) failed", rtscf->signo);
487 }
488
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000489 if (sigaction(rtscf->signo + 1, &sa, NULL) == -1) {
490 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
491 "sigaction(%d, SIG_DFL) failed", rtscf->signo + 1);
492 }
493
494 overflow = 1;
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000495 overflow_current = 0;
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000496 ngx_event_actions.process_events = ngx_rtsig_process_overflow;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000497
Igor Sysoevd962b612004-06-11 06:15:08 +0000498 return NGX_ERROR;
Igor Sysoev22a7c502004-02-17 21:11:27 +0000499
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000500 } else if (signo != -1) {
Igor Sysoev67f450d2004-06-01 06:04:46 +0000501 ngx_accept_mutex_unlock();
502
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000503 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
Igor Sysoev22a7c502004-02-17 21:11:27 +0000504 "sigtimedwait() returned unexpected signal: %d", signo);
Igor Sysoev67f450d2004-06-01 06:04:46 +0000505
Igor Sysoev9139cd22004-02-17 17:53:12 +0000506 return NGX_ERROR;
507 }
508
Igor Sysoevcccc5522004-04-14 20:34:05 +0000509 ngx_accept_mutex_unlock();
510
511 if (expire && delta) {
Igor Sysoev9139cd22004-02-17 17:53:12 +0000512 ngx_event_expire_timers((ngx_msec_t) delta);
513 }
514
Igor Sysoevcccc5522004-04-14 20:34:05 +0000515 if (!ngx_threaded) {
516 ngx_event_process_posted(cycle);
517 }
518
Igor Sysoev956ae652004-06-09 16:36:55 +0000519 if (signo == -1) {
520 return NGX_AGAIN;
521 } else {
522 return NGX_OK;
523 }
Igor Sysoev9139cd22004-02-17 17:53:12 +0000524}
525
526
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000527/* TODO: old cylces */
528
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000529static ngx_int_t ngx_rtsig_process_overflow(ngx_cycle_t *cycle)
Igor Sysoev22a7c502004-02-17 21:11:27 +0000530{
Igor Sysoev87350f22004-06-15 07:55:11 +0000531 int name[2], rtsig_max, rtsig_nr, events, ready;
532 size_t len;
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000533 ngx_int_t tested, n, i;
534 ngx_err_t err;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000535 ngx_connection_t *c;
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000536 ngx_rtsig_conf_t *rtscf;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000537
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000538 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000539
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000540 tested = 0;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000541
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000542 for ( ;; ) {
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000543
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000544 n = 0;
545 while (n < rtscf->overflow_events) {
546
547 if (overflow_current == cycle->connection_n) {
548 break;
549 }
550
551 c = &cycle->connections[overflow_current++];
552
553 if (c->fd == -1) {
554 continue;
555 }
556
557 events = 0;
558
559 if (c->read->active && c->read->event_handler) {
560 events |= POLLIN;
561 }
562
563 if (c->write->active && c->write->event_handler) {
564 events |= POLLOUT;
565 }
566
567 if (events == 0) {
568 continue;
569 }
570
571 overflow_list[n].fd = c->fd;
572 overflow_list[n].events = events;
573 overflow_list[n].revents = 0;
574 n++;
575 }
576
577 if (n == 0) {
578 break;
579 }
580
581 for ( ;; ) {
582 ready = poll(overflow_list, n, 0);
583
584 if (ready == -1) {
585 err = ngx_errno;
586 ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
587 cycle->log, 0,
588 "poll() failed while the overflow recover");
589
590 if (err == NGX_EINTR) {
591 continue;
592 }
593 }
594
595 break;
596 }
597
598 if (ready <= 0) {
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000599 continue;
600 }
601
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000602 for (i = 0; i < n; i++) {
603 c = &cycle->connections[overflow_list[i].fd];
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000604
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000605 if (overflow_list[i].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) {
606 tested++;
607 c->read->ready = 1;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000608
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000609 if (!ngx_threaded) {
610 c->read->event_handler(c->read);
611
612 } else {
613 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
614 return NGX_ERROR;
615 }
616
617 ngx_post_event(c->read);
618 c->read->returned_instance = c->read->instance;
619
620 ngx_mutex_unlock(ngx_posted_events_mutex);
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000621 }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000622 }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000623
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000624 if (overflow_list[i].revents & (POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
625 tested++;
626 c->write->ready = 1;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000627
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000628 if (!ngx_threaded) {
629 c->write->event_handler(c->write);
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000630
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000631 } else {
632 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
633 return NGX_ERROR;
634 }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000635
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000636 ngx_post_event(c->write);
637 c->write->returned_instance = c->write->instance;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000638
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000639 ngx_mutex_unlock(ngx_posted_events_mutex);
640 }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000641 }
642 }
643
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000644 if (tested >= rtscf->overflow_test) {
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000645
646 /*
647 * Check the current rt queue length to prevent the new overflow.
648 *
649 * Learn the /proc/sys/kernel/rtsig-max value because
Igor Sysoev5428ae72004-06-09 20:03:54 +0000650 * it can be changed sisnce the last checking.
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000651 */
652
653 name[0] = CTL_KERN;
654 name[1] = KERN_RTSIGMAX;
655 len = sizeof(rtsig_max);
656 if (sysctl(name, sizeof(name), &rtsig_max, &len, NULL, 0) == -1) {
657 ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
658 "sysctl(KERN_RTSIGMAX) failed");
659 return NGX_ERROR;
660 }
661
662 name[0] = CTL_KERN;
663 name[1] = KERN_RTSIGNR;
664 len = sizeof(rtsig_nr);
665 if (sysctl(name, sizeof(name), &rtsig_nr, &len, NULL, 0) == -1) {
666 ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
667 "sysctl(KERN_RTSIGNR) failed");
668 return NGX_ERROR;
669 }
670
671 /*
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000672 * drain rt signal queue if the /proc/sys/kernel/rtsig-nr is bigger
673 * than "/proc/sys/kernel/rtsig-max / rtsig_overflow_threshold"
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000674 */
675
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000676 if (rtsig_max / rtscf->overflow_threshold < rtsig_nr) {
Igor Sysoev5428ae72004-06-09 20:03:54 +0000677 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
678 "rtsig queue state: %d/%d", rtsig_nr, rtsig_max);
Igor Sysoev956ae652004-06-09 16:36:55 +0000679 while (ngx_rtsig_process_events(cycle) == NGX_OK) { /* void */ }
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000680 }
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000681
682 tested = 0;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000683 }
Igor Sysoev22a7c502004-02-17 21:11:27 +0000684 }
685
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000686 if (!ngx_threaded) {
687 ngx_event_process_posted(cycle);
688 }
689
690 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
691 "rt signal queue overflow recovered");
692
693 overflow = 0;
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000694 ngx_event_actions.process_events = ngx_rtsig_process_events;
Igor Sysoevebfd6c82004-06-09 07:45:27 +0000695
Igor Sysoev22a7c502004-02-17 21:11:27 +0000696 return NGX_OK;
697}
698
699
Igor Sysoev9139cd22004-02-17 17:53:12 +0000700static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle)
701{
702 ngx_rtsig_conf_t *rtscf;
703
704 ngx_test_null(rtscf, ngx_palloc(cycle->pool, sizeof(ngx_rtsig_conf_t)),
705 NGX_CONF_ERROR);
706
707 rtscf->signo = NGX_CONF_UNSET;
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000708 rtscf->overflow_events = NGX_CONF_UNSET;
709 rtscf->overflow_test = NGX_CONF_UNSET;
710 rtscf->overflow_threshold = NGX_CONF_UNSET;
Igor Sysoev9139cd22004-02-17 17:53:12 +0000711
712 return rtscf;
713}
714
715
716static char *ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf)
717{
718 ngx_rtsig_conf_t *rtscf = conf;
719
720 /* LinuxThreads use the first 3 RT signals */
721 ngx_conf_init_value(rtscf->signo, SIGRTMIN + 10);
722
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000723 ngx_conf_init_value(rtscf->overflow_events, 16);
Igor Sysoev87350f22004-06-15 07:55:11 +0000724 ngx_conf_init_value(rtscf->overflow_test, 32);
725 ngx_conf_init_value(rtscf->overflow_threshold, 10);
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000726
Igor Sysoev9139cd22004-02-17 17:53:12 +0000727 return NGX_CONF_OK;
728}