Mercurial > hg > nginx
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 |