Annotation of embedaddon/nginx/src/event/modules/ngx_rtsig_module.c, revision 1.1.1.1

1.1       misho       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: 
                     44: int ngx_linux_rtsig_max;
                     45: 
                     46: #endif
                     47: 
                     48: 
                     49: typedef struct {
                     50:     ngx_uint_t  signo;
                     51:     ngx_uint_t  overflow_events;
                     52:     ngx_uint_t  overflow_test;
                     53:     ngx_uint_t  overflow_threshold;
                     54: } ngx_rtsig_conf_t;
                     55: 
                     56: 
                     57: extern ngx_event_module_t  ngx_poll_module_ctx;
                     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"),
                     90:       NGX_EVENT_CONF|NGX_CONF_TAKE1,
                     91:       ngx_conf_set_num_slot,
                     92:       0,
                     93:       offsetof(ngx_rtsig_conf_t, signo),
                     94:       NULL },
                     95: 
                     96:     { ngx_string("rtsig_overflow_events"),
                     97:       NGX_EVENT_CONF|NGX_CONF_TAKE1,
                     98:       ngx_conf_set_num_slot,
                     99:       0,
                    100:       offsetof(ngx_rtsig_conf_t, overflow_events),
                    101:       NULL },
                    102: 
                    103:     { ngx_string("rtsig_overflow_test"),
                    104:       NGX_EVENT_CONF|NGX_CONF_TAKE1,
                    105:       ngx_conf_set_num_slot,
                    106:       0,
                    107:       offsetof(ngx_rtsig_conf_t, overflow_test),
                    108:       NULL },
                    109: 
                    110:     { ngx_string("rtsig_overflow_threshold"),
                    111:       NGX_EVENT_CONF|NGX_CONF_TAKE1,
                    112:       ngx_conf_set_num_slot,
                    113:       0,
                    114:       offsetof(ngx_rtsig_conf_t, overflow_threshold),
                    115:       &ngx_overflow_threshold_bounds },
                    116: 
                    117:       ngx_null_command
                    118: };
                    119: 
                    120: 
                    121: ngx_event_module_t  ngx_rtsig_module_ctx = {
                    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: 
                    141: ngx_module_t  ngx_rtsig_module = {
                    142:     NGX_MODULE_V1,
                    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 */
                    153:     NGX_MODULE_V1_PADDING
                    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) {
                    171:         ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                    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: 
                    190:     ngx_event_flags = NGX_USE_RTSIG_EVENT
                    191:                       |NGX_USE_GREEDY_EVENT
                    192:                       |NGX_USE_FD_EVENT;
                    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: 
                    215:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    216:                        "rtsig enable connection: fd:%d", c->fd);
                    217: 
                    218:         if (fcntl(c->fd, F_SETOWN, ngx_pid) == -1) {
                    219:             ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                    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: 
                    232:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    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) {
                    236:         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                    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) {
                    242:         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                    243:                       "fcntl(F_SETSIG) failed");
                    244:         return NGX_ERROR;
                    245:     }
                    246: 
                    247:     if (fcntl(c->fd, F_SETOWN, ngx_pid) == -1) {
                    248:         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                    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) {
                    255:         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                    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: {
                    271:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    272:                    "rtsig del connection: fd:%d", c->fd);
                    273: 
                    274:     if ((flags & NGX_DISABLE_EVENT) && c->read->accept) {
                    275: 
                    276:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    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) {
                    291:         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                    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: 
                    325:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    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: 
                    335:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, err,
                    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: 
                    355:         ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
                    356:                       cycle->log, err, "sigtimedwait() failed");
                    357:         return NGX_ERROR;
                    358:     }
                    359: 
                    360:     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    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: 
                    396:             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    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 ?
                    408:                                &ngx_posted_accept_events : &ngx_posted_events);
                    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) {
                    424:                 ngx_locked_post_event(wev, &ngx_posted_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) {
                    451:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                    452:                           "sigaction(%d, SIG_DFL) failed", rtscf->signo);
                    453:         }
                    454: 
                    455:         if (sigaction(rtscf->signo + 1, &sa, NULL) == -1) {
                    456:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                    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: 
                    487:     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    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: 
                    536:             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    537:                            "rtsig overflow poll:%d", ready);
                    538: 
                    539:             if (ready == -1) {
                    540:                 err = ngx_errno;
                    541:                 ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
                    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 ?
                    585:                                &ngx_posted_accept_events : &ngx_posted_events);
                    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) {
                    612:                     ngx_locked_post_event(wev, &ngx_posted_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) {
                    661:                     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    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;
                    711:     rtscf->overflow_events = NGX_CONF_UNSET;
                    712:     rtscf->overflow_test = NGX_CONF_UNSET;
                    713:     rtscf->overflow_threshold = 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: 
                    727:     ngx_conf_init_uint_value(rtscf->overflow_events, 16);
                    728:     ngx_conf_init_uint_value(rtscf->overflow_test, 32);
                    729:     ngx_conf_init_uint_value(rtscf->overflow_threshold, 10);
                    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: 
                    742:     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                    743:                        "\"rtsig_overflow_threshold\" is not supported "
                    744:                        "since Linux 2.6.6-mm2, ignored");
                    745: 
                    746:     return NGX_CONF_OK;
                    747: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>