Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_rtsig_module.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 
12 
13 #if (NGX_TEST_BUILD_RTSIG)
14 
15 #if (NGX_DARWIN)
16 
17 #define SIGRTMIN 33
18 #define si_fd __pad[0]
19 
20 #else
21 
22 #ifdef SIGRTMIN
23 #define si_fd _reason.__spare__.__spare2__[0]
24 #else
25 #define SIGRTMIN 33
26 #define si_fd __spare__[0]
27 #endif
28 
29 #endif
30 
31 #define F_SETSIG 10
32 #define KERN_RTSIGNR 30
33 #define KERN_RTSIGMAX 31
34 
35 int sigtimedwait(const sigset_t *set, siginfo_t *info,
36  const struct timespec *timeout);
37 
38 int sigtimedwait(const sigset_t *set, siginfo_t *info,
39  const struct timespec *timeout)
40 {
41  return -1;
42 }
43 
45 
46 #endif
47 
48 
49 typedef struct {
55 
56 
58 
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,
63  ngx_uint_t flags);
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);
68 
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);
73 
74 
75 static sigset_t set;
76 static ngx_uint_t overflow, overflow_current;
77 static struct pollfd *overflow_list;
78 
79 
80 static ngx_str_t rtsig_name = ngx_string("rtsig");
81 
82 static ngx_conf_num_bounds_t ngx_overflow_threshold_bounds = {
83  ngx_check_ngx_overflow_threshold_bounds, 2, 10
84 };
85 
86 
87 static ngx_command_t ngx_rtsig_commands[] = {
88 
89  { ngx_string("rtsig_signo"),
92  0,
93  offsetof(ngx_rtsig_conf_t, signo),
94  NULL },
95 
96  { ngx_string("rtsig_overflow_events"),
99  0,
100  offsetof(ngx_rtsig_conf_t, overflow_events),
101  NULL },
102 
103  { ngx_string("rtsig_overflow_test"),
106  0,
107  offsetof(ngx_rtsig_conf_t, overflow_test),
108  NULL },
109 
110  { ngx_string("rtsig_overflow_threshold"),
113  0,
114  offsetof(ngx_rtsig_conf_t, overflow_threshold),
115  &ngx_overflow_threshold_bounds },
116 
118 };
119 
120 
122  &rtsig_name,
123  ngx_rtsig_create_conf, /* create configuration */
124  ngx_rtsig_init_conf, /* init configuration */
125 
126  {
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 */
137  }
138 
139 };
140 
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 */
154 };
155 
156 
157 static ngx_int_t
158 ngx_rtsig_init(ngx_cycle_t *cycle, ngx_msec_t timer)
159 {
160  ngx_rtsig_conf_t *rtscf;
161 
162  rtscf = ngx_event_get_conf(cycle->conf_ctx, ngx_rtsig_module);
163 
164  sigemptyset(&set);
165  sigaddset(&set, (int) rtscf->signo);
166  sigaddset(&set, (int) rtscf->signo + 1);
167  sigaddset(&set, SIGIO);
168  sigaddset(&set, SIGALRM);
169 
170  if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
172  "sigprocmask() failed");
173  return NGX_ERROR;
174  }
175 
176  if (overflow_list) {
177  ngx_free(overflow_list);
178  }
179 
180  overflow_list = ngx_alloc(sizeof(struct pollfd) * rtscf->overflow_events,
181  cycle->log);
182  if (overflow_list == NULL) {
183  return NGX_ERROR;
184  }
185 
186  ngx_io = ngx_os_io;
187 
188  ngx_event_actions = ngx_rtsig_module_ctx.actions;
189 
193 
194  return NGX_OK;
195 }
196 
197 
198 static void
199 ngx_rtsig_done(ngx_cycle_t *cycle)
200 {
201  ngx_free(overflow_list);
202 
203  overflow_list = NULL;
204 }
205 
206 
207 static ngx_int_t
208 ngx_rtsig_add_connection(ngx_connection_t *c)
209 {
210  ngx_uint_t signo;
211  ngx_rtsig_conf_t *rtscf;
212 
213  if (c->read->accept && c->read->disabled) {
214 
216  "rtsig enable connection: fd:%d", c->fd);
217 
218  if (fcntl(c->fd, F_SETOWN, ngx_pid) == -1) {
220  "fcntl(F_SETOWN) failed");
221  return NGX_ERROR;
222  }
223 
224  c->read->active = 1;
225  c->read->disabled = 0;
226  }
227 
228  rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
229 
230  signo = rtscf->signo + c->read->instance;
231 
233  "rtsig add connection: fd:%d signo:%ui", c->fd, signo);
234 
235  if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) == -1) {
237  "fcntl(O_RDWR|O_NONBLOCK|O_ASYNC) failed");
238  return NGX_ERROR;
239  }
240 
241  if (fcntl(c->fd, F_SETSIG, (int) signo) == -1) {
243  "fcntl(F_SETSIG) failed");
244  return NGX_ERROR;
245  }
246 
247  if (fcntl(c->fd, F_SETOWN, ngx_pid) == -1) {
249  "fcntl(F_SETOWN) failed");
250  return NGX_ERROR;
251  }
252 
253 #if (NGX_HAVE_ONESIGFD)
254  if (fcntl(c->fd, F_SETAUXFL, O_ONESIGFD) == -1) {
256  "fcntl(F_SETAUXFL) failed");
257  return NGX_ERROR;
258  }
259 #endif
260 
261  c->read->active = 1;
262  c->write->active = 1;
263 
264  return NGX_OK;
265 }
266 
267 
268 static ngx_int_t
269 ngx_rtsig_del_connection(ngx_connection_t *c, ngx_uint_t flags)
270 {
272  "rtsig del connection: fd:%d", c->fd);
273 
274  if ((flags & NGX_DISABLE_EVENT) && c->read->accept) {
275 
277  "rtsig disable connection: fd:%d", c->fd);
278 
279  c->read->active = 0;
280  c->read->disabled = 1;
281  return NGX_OK;
282  }
283 
284  if (flags & NGX_CLOSE_EVENT) {
285  c->read->active = 0;
286  c->write->active = 0;
287  return NGX_OK;
288  }
289 
290  if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK) == -1) {
292  "fcntl(O_RDWR|O_NONBLOCK) failed");
293  return NGX_ERROR;
294  }
295 
296  c->read->active = 0;
297  c->write->active = 0;
298 
299  return NGX_OK;
300 }
301 
302 
303 static ngx_int_t
304 ngx_rtsig_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
305 {
306  int signo;
307  ngx_int_t instance;
308  ngx_err_t err;
309  siginfo_t si;
310  ngx_event_t *rev, *wev, **queue;
311  struct timespec ts, *tp;
312  struct sigaction sa;
313  ngx_connection_t *c;
314  ngx_rtsig_conf_t *rtscf;
315 
316  if (timer == NGX_TIMER_INFINITE) {
317  tp = NULL;
318 
319  } else {
320  ts.tv_sec = timer / 1000;
321  ts.tv_nsec = (timer % 1000) * 1000000;
322  tp = &ts;
323  }
324 
326  "rtsig timer: %M", timer);
327 
328  /* Linux's sigwaitinfo() is sigtimedwait() with the NULL timeout pointer */
329 
330  signo = sigtimedwait(&set, &si, tp);
331 
332  if (signo == -1) {
333  err = ngx_errno;
334 
336  "rtsig signo:%d", signo);
337 
338  if (flags & NGX_UPDATE_TIME) {
339  ngx_time_update();
340  }
341 
342  if (err == NGX_EAGAIN) {
343 
344  /* timeout */
345 
346  if (timer != NGX_TIMER_INFINITE) {
347  return NGX_AGAIN;
348  }
349 
350  ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
351  "sigtimedwait() returned EAGAIN without timeout");
352  return NGX_ERROR;
353  }
354 
356  cycle->log, err, "sigtimedwait() failed");
357  return NGX_ERROR;
358  }
359 
361  "rtsig signo:%d fd:%d band:%04Xd",
362  signo, si.si_fd, si.si_band);
363 
364  if (flags & NGX_UPDATE_TIME) {
365  ngx_time_update();
366  }
367 
368  rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
369 
370  if (signo == (int) rtscf->signo || signo == (int) rtscf->signo + 1) {
371 
372  if (overflow && (ngx_uint_t) si.si_fd > overflow_current) {
373  return NGX_OK;
374  }
375 
376  c = ngx_cycle->files[si.si_fd];
377 
378  if (c == NULL) {
379 
380  /* the stale event */
381 
382  return NGX_OK;
383  }
384 
385  instance = signo - (int) rtscf->signo;
386 
387  rev = c->read;
388 
389  if (rev->instance != instance) {
390 
391  /*
392  * the stale event from a file descriptor
393  * that was just closed in this iteration
394  */
395 
397  "rtsig: stale event %p", c);
398 
399  return NGX_OK;
400  }
401 
402  if ((si.si_band & (POLLIN|POLLHUP|POLLERR)) && rev->active) {
403 
404  rev->ready = 1;
405 
406  if (flags & NGX_POST_EVENTS) {
407  queue = (ngx_event_t **) (rev->accept ?
409 
410  ngx_locked_post_event(rev, queue);
411 
412  } else {
413  rev->handler(rev);
414  }
415  }
416 
417  wev = c->write;
418 
419  if ((si.si_band & (POLLOUT|POLLHUP|POLLERR)) && wev->active) {
420 
421  wev->ready = 1;
422 
423  if (flags & NGX_POST_EVENTS) {
425 
426  } else {
427  wev->handler(wev);
428  }
429  }
430 
431  return NGX_OK;
432 
433  } else if (signo == SIGALRM) {
434 
435  ngx_time_update();
436 
437  return NGX_OK;
438 
439  } else if (signo == SIGIO) {
440 
441  ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
442  "rt signal queue overflowed");
443 
444  /* flush the RT signal queue */
445 
446  ngx_memzero(&sa, sizeof(struct sigaction));
447  sa.sa_handler = SIG_DFL;
448  sigemptyset(&sa.sa_mask);
449 
450  if (sigaction(rtscf->signo, &sa, NULL) == -1) {
452  "sigaction(%d, SIG_DFL) failed", rtscf->signo);
453  }
454 
455  if (sigaction(rtscf->signo + 1, &sa, NULL) == -1) {
457  "sigaction(%d, SIG_DFL) failed", rtscf->signo + 1);
458  }
459 
460  overflow = 1;
461  overflow_current = 0;
462  ngx_event_actions.process_events = ngx_rtsig_process_overflow;
463 
464  return NGX_ERROR;
465 
466  }
467 
468  ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
469  "sigtimedwait() returned unexpected signal: %d", signo);
470 
471  return NGX_ERROR;
472 }
473 
474 
475 static ngx_int_t
476 ngx_rtsig_process_overflow(ngx_cycle_t *cycle, ngx_msec_t timer,
477  ngx_uint_t flags)
478 {
479  int name[2], rtsig_max, rtsig_nr, events, ready;
480  size_t len;
481  ngx_err_t err;
482  ngx_uint_t tested, n, i;
483  ngx_event_t *rev, *wev, **queue;
484  ngx_connection_t *c;
485  ngx_rtsig_conf_t *rtscf;
486 
488  "rtsig process overflow");
489 
490  rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
491 
492  tested = 0;
493 
494  for ( ;; ) {
495 
496  n = 0;
497  while (n < rtscf->overflow_events) {
498 
499  if (overflow_current == cycle->connection_n) {
500  break;
501  }
502 
503  c = cycle->files[overflow_current++];
504 
505  if (c == NULL || c->fd == -1) {
506  continue;
507  }
508 
509  events = 0;
510 
511  if (c->read->active && c->read->handler) {
512  events |= POLLIN;
513  }
514 
515  if (c->write->active && c->write->handler) {
516  events |= POLLOUT;
517  }
518 
519  if (events == 0) {
520  continue;
521  }
522 
523  overflow_list[n].fd = c->fd;
524  overflow_list[n].events = events;
525  overflow_list[n].revents = 0;
526  n++;
527  }
528 
529  if (n == 0) {
530  break;
531  }
532 
533  for ( ;; ) {
534  ready = poll(overflow_list, n, 0);
535 
537  "rtsig overflow poll:%d", ready);
538 
539  if (ready == -1) {
540  err = ngx_errno;
542  cycle->log, 0,
543  "poll() failed while the overflow recover");
544 
545  if (err == NGX_EINTR) {
546  continue;
547  }
548  }
549 
550  break;
551  }
552 
553  if (ready <= 0) {
554  continue;
555  }
556 
557  ngx_mutex_lock(ngx_posted_events_mutex);
558 
559  for (i = 0; i < n; i++) {
560  c = cycle->files[overflow_list[i].fd];
561 
562  if (c == NULL) {
563  continue;
564  }
565 
566  rev = c->read;
567 
568  if (rev->active
569  && !rev->closed
570  && rev->handler
571  && (overflow_list[i].revents
572  & (POLLIN|POLLERR|POLLHUP|POLLNVAL)))
573  {
574  tested++;
575 
576  if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
577  rev->posted_ready = 1;
578 
579  } else {
580  rev->ready = 1;
581  }
582 
583  if (flags & NGX_POST_EVENTS) {
584  queue = (ngx_event_t **) (rev->accept ?
586 
587  ngx_locked_post_event(rev, queue);
588 
589  } else {
590  rev->handler(rev);
591  }
592  }
593 
594  wev = c->write;
595 
596  if (wev->active
597  && !wev->closed
598  && wev->handler
599  && (overflow_list[i].revents
600  & (POLLOUT|POLLERR|POLLHUP|POLLNVAL)))
601  {
602  tested++;
603 
604  if (flags & NGX_POST_THREAD_EVENTS) {
605  wev->posted_ready = 1;
606 
607  } else {
608  wev->ready = 1;
609  }
610 
611  if (flags & NGX_POST_EVENTS) {
613 
614  } else {
615  wev->handler(wev);
616  }
617  }
618  }
619 
620  ngx_mutex_unlock(ngx_posted_events_mutex);
621 
622  if (tested >= rtscf->overflow_test) {
623 
624  if (ngx_linux_rtsig_max) {
625 
626  /*
627  * Check the current rt queue length to prevent
628  * the new overflow.
629  *
630  * learn the "/proc/sys/kernel/rtsig-max" value because
631  * it can be changed since the last checking
632  */
633 
634  name[0] = CTL_KERN;
635  name[1] = KERN_RTSIGMAX;
636  len = sizeof(rtsig_max);
637 
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");
641  return NGX_ERROR;
642  }
643 
644  /* name[0] = CTL_KERN; */
645  name[1] = KERN_RTSIGNR;
646  len = sizeof(rtsig_nr);
647 
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");
651  return NGX_ERROR;
652  }
653 
654  /*
655  * drain the rt signal queue if the /"proc/sys/kernel/rtsig-nr"
656  * is bigger than
657  * "/proc/sys/kernel/rtsig-max" / "rtsig_overflow_threshold"
658  */
659 
660  if (rtsig_max / (int) rtscf->overflow_threshold < rtsig_nr) {
662  "rtsig queue state: %d/%d",
663  rtsig_nr, rtsig_max);
664  while (ngx_rtsig_process_events(cycle, 0, flags) == NGX_OK)
665  {
666  /* void */
667  }
668  }
669 
670  } else {
671 
672  /*
673  * Linux has not KERN_RTSIGMAX since 2.6.6-mm2
674  * so drain the rt signal queue unconditionally
675  */
676 
677  while (ngx_rtsig_process_events(cycle, 0, flags) == NGX_OK) {
678  /* void */
679  }
680  }
681 
682  tested = 0;
683  }
684  }
685 
686  if (flags & NGX_UPDATE_TIME) {
687  ngx_time_update();
688  }
689 
690  ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
691  "rt signal queue overflow recovered");
692 
693  overflow = 0;
694  ngx_event_actions.process_events = ngx_rtsig_process_events;
695 
696  return NGX_OK;
697 }
698 
699 
700 static void *
701 ngx_rtsig_create_conf(ngx_cycle_t *cycle)
702 {
703  ngx_rtsig_conf_t *rtscf;
704 
705  rtscf = ngx_palloc(cycle->pool, sizeof(ngx_rtsig_conf_t));
706  if (rtscf == NULL) {
707  return NULL;
708  }
709 
710  rtscf->signo = NGX_CONF_UNSET;
712  rtscf->overflow_test = NGX_CONF_UNSET;
714 
715  return rtscf;
716 }
717 
718 
719 static char *
720 ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf)
721 {
722  ngx_rtsig_conf_t *rtscf = conf;
723 
724  /* LinuxThreads use the first 3 RT signals */
725  ngx_conf_init_uint_value(rtscf->signo, SIGRTMIN + 10);
726 
730 
731  return NGX_CONF_OK;
732 }
733 
734 
735 static char *
736 ngx_check_ngx_overflow_threshold_bounds(ngx_conf_t *cf, void *post, void *data)
737 {
738  if (ngx_linux_rtsig_max) {
739  return ngx_conf_check_num_bounds(cf, post, data);
740  }
741 
743  "\"rtsig_overflow_threshold\" is not supported "
744  "since Linux 2.6.6-mm2, ignored");
745 
746  return NGX_CONF_OK;
747 }