Annotation of embedaddon/nginx/src/event/modules/ngx_rtsig_module.c, revision 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>