comparison src/event/modules/ngx_rtsig_module.c @ 348:68ff8000a974

nginx-0.0.3-2004-06-09-11:45:27 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 09 Jun 2004 07:45:27 +0000
parents 55e496a8ece3
children a958aa92f9a5
comparison
equal deleted inserted replaced
347:f48d579daf78 348:68ff8000a974
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 10
11 11
12 #if (TEST_BUILD_RTSIG) 12 #if (TEST_BUILD_RTSIG)
13 13
14 #define F_SETSIG 10 14 #define F_SETSIG 10
15 #define SIGRTMIN 33 15 #define SIGRTMIN 33
16 #define si_fd __spare__[0] 16 #define si_fd __spare__[0]
17 #define KERN_RTSIGNR 30
18 #define KERN_RTSIGMAX 31
17 19
18 int sigtimedwait(const sigset_t *set, siginfo_t *info, 20 int sigtimedwait(const sigset_t *set, siginfo_t *info,
19 const struct timespec *timeout) 21 const struct timespec *timeout)
20 { 22 {
21 return -1; 23 return -1;
29 } ngx_rtsig_conf_t; 31 } ngx_rtsig_conf_t;
30 32
31 33
32 extern ngx_event_module_t ngx_poll_module_ctx; 34 extern ngx_event_module_t ngx_poll_module_ctx;
33 35
34 static int ngx_rtsig_init(ngx_cycle_t *cycle); 36 static ngx_int_t ngx_rtsig_init(ngx_cycle_t *cycle);
35 static void ngx_rtsig_done(ngx_cycle_t *cycle); 37 static void ngx_rtsig_done(ngx_cycle_t *cycle);
36 static int ngx_rtsig_add_connection(ngx_connection_t *c); 38 static ngx_int_t ngx_rtsig_add_connection(ngx_connection_t *c);
37 static int ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags); 39 static ngx_int_t ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags);
38 static int ngx_rtsig_process_events(ngx_cycle_t *cycle); 40 static ngx_int_t ngx_rtsig_process_events(ngx_cycle_t *cycle);
39 static int ngx_rtsig_process_overflow(ngx_cycle_t *cycle); 41 static ngx_int_t ngx_rtsig_process_overflow(ngx_cycle_t *cycle);
40 42
41 static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle); 43 static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle);
42 static char *ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf); 44 static char *ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf);
43 45
44 46
45 static sigset_t set; 47 static sigset_t set;
48 static ngx_uint_t overflow, current;
46 49
47 50
48 static ngx_str_t rtsig_name = ngx_string("rtsig"); 51 static ngx_str_t rtsig_name = ngx_string("rtsig");
49 52
50 static ngx_command_t ngx_rtsig_commands[] = { 53 static ngx_command_t ngx_rtsig_commands[] = {
87 NULL, /* init module */ 90 NULL, /* init module */
88 NULL /* init child */ 91 NULL /* init child */
89 }; 92 };
90 93
91 94
92 static int ngx_rtsig_init(ngx_cycle_t *cycle) 95 static ngx_int_t ngx_rtsig_init(ngx_cycle_t *cycle)
93 { 96 {
94 ngx_rtsig_conf_t *rtscf; 97 ngx_rtsig_conf_t *rtscf;
95 98
96 if (ngx_poll_module_ctx.actions.init(cycle) == NGX_ERROR) { 99 if (ngx_poll_module_ctx.actions.init(cycle) == NGX_ERROR) {
97 return NGX_ERROR; 100 return NGX_ERROR;
126 { 129 {
127 ngx_poll_module_ctx.actions.done(cycle); 130 ngx_poll_module_ctx.actions.done(cycle);
128 } 131 }
129 132
130 133
131 static int ngx_rtsig_add_connection(ngx_connection_t *c) 134 static ngx_int_t ngx_rtsig_add_connection(ngx_connection_t *c)
132 { 135 {
133 int signo; 136 int signo;
134 ngx_rtsig_conf_t *rtscf; 137 ngx_rtsig_conf_t *rtscf;
135 138
136 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module); 139 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
171 174
172 return NGX_OK; 175 return NGX_OK;
173 } 176 }
174 177
175 178
176 static int ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags) 179 static ngx_int_t ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags)
177 { 180 {
178 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 181 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
179 "rtsig del connection: fd:%d", c->fd); 182 "rtsig del connection: fd:%d", c->fd);
180 183
181 if (!(flags & NGX_CLOSE_EVENT)) { 184 if (!(flags & NGX_CLOSE_EVENT)) {
191 194
192 return NGX_OK; 195 return NGX_OK;
193 } 196 }
194 197
195 198
196 int ngx_rtsig_process_events(ngx_cycle_t *cycle) 199 ngx_int_t ngx_rtsig_process_events(ngx_cycle_t *cycle)
197 { 200 {
198 int signo; 201 int signo;
199 ngx_int_t instance, i; 202 ngx_int_t instance, i;
200 ngx_uint_t expire; 203 ngx_uint_t expire;
201 size_t n; 204 size_t n;
207 struct sigaction sa; 210 struct sigaction sa;
208 ngx_epoch_msec_t delta; 211 ngx_epoch_msec_t delta;
209 ngx_connection_t *c; 212 ngx_connection_t *c;
210 ngx_rtsig_conf_t *rtscf; 213 ngx_rtsig_conf_t *rtscf;
211 214
212 for ( ;; ) { 215 if (overflow) {
213 timer = ngx_event_find_timer(); 216 timer = 0;
214 217 expire = 0;
215 if (timer != 0) { 218
216 break; 219 } else {
217 } 220 for ( ;; ) {
218 221 timer = ngx_event_find_timer();
219 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, 222
220 "rtsig expired timer"); 223 if (timer != 0) {
221 224 break;
222 ngx_event_expire_timers((ngx_msec_t) 225 }
226
227 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
228 "rtsig expired timer");
229
230 ngx_event_expire_timers((ngx_msec_t)
223 (ngx_elapsed_msec - ngx_old_elapsed_msec)); 231 (ngx_elapsed_msec - ngx_old_elapsed_msec));
224 } 232 }
225 233
226 expire = 1; 234 expire = 1;
227 235
228 if (ngx_accept_mutex) { 236 if (ngx_accept_mutex) {
229 if (ngx_accept_disabled > 0) { 237 if (ngx_accept_disabled > 0) {
230 ngx_accept_disabled--; 238 ngx_accept_disabled--;
231 239
232 } else { 240 } else {
233 if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { 241 if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
234 return NGX_ERROR; 242 return NGX_ERROR;
235 } 243 }
236 244
237 if (ngx_accept_mutex_held == 0 245 if (ngx_accept_mutex_held == 0
238 && (timer == NGX_TIMER_INFINITE 246 && (timer == NGX_TIMER_INFINITE
239 || timer > ngx_accept_mutex_delay)) 247 || timer > ngx_accept_mutex_delay))
240 { 248 {
241 timer = ngx_accept_mutex_delay; 249 timer = ngx_accept_mutex_delay;
242 expire = 0; 250 expire = 0;
243 } 251 }
252 }
244 } 253 }
245 } 254 }
246 255
247 if (timer == NGX_TIMER_INFINITE) { 256 if (timer == NGX_TIMER_INFINITE) {
248 tp = NULL; 257 tp = NULL;
263 272
264 signo = sigtimedwait(&set, &si, tp); 273 signo = sigtimedwait(&set, &si, tp);
265 274
266 if (signo == -1) { 275 if (signo == -1) {
267 err = ngx_errno; 276 err = ngx_errno;
277
278 if (err == NGX_EAGAIN) {
279
280 if (timer == NGX_TIMER_INFINITE) {
281 ngx_accept_mutex_unlock();
282 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
283 "sigtimedwait() returned EAGAIN without timeout");
284 return NGX_ERROR;
285 }
286
287 err = 0;
288 }
289
268 } else { 290 } else {
269 err = 0; 291 err = 0;
270 } 292 }
271 293
272 ngx_gettimeofday(&tv); 294 ngx_gettimeofday(&tv);
293 "rtsig signo:%d fd:%d band:%X", signo, si.si_fd, si.si_band); 315 "rtsig signo:%d fd:%d band:%X", signo, si.si_fd, si.si_band);
294 316
295 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module); 317 rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
296 318
297 if (signo == rtscf->signo || signo == rtscf->signo + 1) { 319 if (signo == rtscf->signo || signo == rtscf->signo + 1) {
320
321 if (overflow && (ngx_uint_t) si.si_fd > current) {
322 return NGX_OK;
323 }
298 324
299 /* TODO: old_cycles */ 325 /* TODO: old_cycles */
300 326
301 c = &ngx_cycle->connections[si.si_fd]; 327 c = &ngx_cycle->connections[si.si_fd];
302 328
372 } 398 }
373 399
374 } else if (signo == SIGIO) { 400 } else if (signo == SIGIO) {
375 ngx_accept_mutex_unlock(); 401 ngx_accept_mutex_unlock();
376 402
377 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, 403 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
378 "signal queue overflowed: " 404 "rt signal queue overflowed");
379 "SIGIO, fd:%d, band:%X", si.si_fd, si.si_band); 405
380 406 /* flush the RT signal queue */
381 /* TODO: flush all the used RT signals */
382 407
383 ngx_memzero(&sa, sizeof(struct sigaction)); 408 ngx_memzero(&sa, sizeof(struct sigaction));
384 sa.sa_handler = SIG_DFL; 409 sa.sa_handler = SIG_DFL;
385 sigemptyset(&sa.sa_mask); 410 sigemptyset(&sa.sa_mask);
411
386 if (sigaction(rtscf->signo, &sa, NULL) == -1) { 412 if (sigaction(rtscf->signo, &sa, NULL) == -1) {
387 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, 413 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
388 "sigaction(%d, SIG_DFL) failed", rtscf->signo); 414 "sigaction(%d, SIG_DFL) failed", rtscf->signo);
389 } 415 }
390 416
391 ngx_event_actions = ngx_poll_module_ctx.actions; 417 if (sigaction(rtscf->signo + 1, &sa, NULL) == -1) {
418 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
419 "sigaction(%d, SIG_DFL) failed", rtscf->signo + 1);
420 }
421
422 overflow = 1;
423 current = 0;
392 ngx_event_actions.process = ngx_rtsig_process_overflow; 424 ngx_event_actions.process = ngx_rtsig_process_overflow;
393 ngx_event_flags = NGX_OVERFLOW_EVENT 425
394 |NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT; 426 return NGX_OK;
395 427
396 /* STUB: add events. WHAT to do with fcntl()s ? */ 428 } else if (signo != -1) {
397
398
399 } else {
400 ngx_accept_mutex_unlock(); 429 ngx_accept_mutex_unlock();
401 430
402 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, 431 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
403 "sigtimedwait() returned unexpected signal: %d", signo); 432 "sigtimedwait() returned unexpected signal: %d", signo);
404 433
417 446
418 return NGX_OK; 447 return NGX_OK;
419 } 448 }
420 449
421 450
422 static int ngx_rtsig_process_overflow(ngx_cycle_t *cycle) 451 static ngx_int_t ngx_rtsig_process_overflow(ngx_cycle_t *cycle)
423 { 452 {
424 if (ngx_poll_module_ctx.actions.process(cycle) == NGX_OK) { 453 int name[2], len, rtsig_max, rtsig_nr;
425 ngx_event_actions = ngx_rtsig_module_ctx.actions; 454 ngx_uint_t i;
426 ngx_event_flags = NGX_USE_RTSIG_EVENT; 455 ngx_connection_t *c;
427 } 456
457 /* TODO: old cylces */
458
459 c = cycle->connections;
460 for (current = 0; current < cycle->connection_n; current++) {
461
462 i = current;
463
464 if (c[i].fd == -1) {
465 continue;
466 }
467
468 if (c[i].read->active && c[i].read->event_handler) {
469 c[i].read->ready = 1;
470
471 if (!ngx_threaded) {
472 c[i].read->event_handler(c[i].read);
473
474 } else {
475 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
476 return NGX_ERROR;
477 }
478
479 ngx_post_event(c[i].read);
480
481 ngx_mutex_unlock(ngx_posted_events_mutex);
482 }
483 }
484
485 if (c[i].write->active && c[i].write->event_handler) {
486 c[i].write->ready = 1;
487
488 if (!ngx_threaded) {
489 c[i].write->event_handler(c[i].write);
490
491 } else {
492 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
493 return NGX_ERROR;
494 }
495
496 ngx_post_event(c[i].write);
497
498 ngx_mutex_unlock(ngx_posted_events_mutex);
499 }
500 }
501
502 if (i && (i % 100 == 0)) {
503
504 /*
505 * Check the current rt queue length to prevent the new overflow.
506 *
507 * Learn the /proc/sys/kernel/rtsig-max value because
508 * it can be changed sisnce the last checking
509 */
510
511 name[0] = CTL_KERN;
512 name[1] = KERN_RTSIGMAX;
513 len = sizeof(rtsig_max);
514 if (sysctl(name, sizeof(name), &rtsig_max, &len, NULL, 0) == -1) {
515 ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
516 "sysctl(KERN_RTSIGMAX) failed");
517 return NGX_ERROR;
518 }
519
520 name[0] = CTL_KERN;
521 name[1] = KERN_RTSIGNR;
522 len = sizeof(rtsig_nr);
523 if (sysctl(name, sizeof(name), &rtsig_nr, &len, NULL, 0) == -1) {
524 ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
525 "sysctl(KERN_RTSIGNR) failed");
526 return NGX_ERROR;
527 }
528
529 /*
530 * drain rt signal queue if the /proc/sys/kernel/rtsig-nr
531 * is bigger then "/proc/sys/kernel/rtsig-max / 4"
532 */
533
534 while (rtsig_max / 4 < rtsig_nr) {
535 ngx_rtsig_process_events(cycle);
536 rtsig_nr--;
537 }
538 }
539 }
540
541 if (!ngx_threaded) {
542 ngx_event_process_posted(cycle);
543 }
544
545 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
546 "rt signal queue overflow recovered");
547
548 overflow = 0;
549 ngx_event_actions.process = ngx_rtsig_process_events;
428 550
429 return NGX_OK; 551 return NGX_OK;
430 } 552 }
431 553
432 554