# HG changeset patch # User Igor Sysoev # Date 1075484340 0 # Node ID 6753e8cdaa2cb1038a32c409b41322e6b3254f9a # Parent e6c005b66b3ad6cdc35144fa391b48bb691aa133 nginx-0.0.1-2004-01-30-20:39:00 import diff --git a/auto/options b/auto/options --- a/auto/options +++ b/auto/options @@ -6,6 +6,7 @@ OBJS=objs TEST_BUILD_DEVPOLL=NO TEST_BUILD_EPOLL=NO +TEST_BUILD_SIGIO=NO SELECT=YES POLL=YES @@ -56,6 +57,7 @@ do --test-build-devpoll) TEST_BUILD_DEVPOLL=YES ;; --test-build-epoll) TEST_BUILD_EPOLL=YES ;; + --test-build-sigio) TEST_BUILD_SIGIO=YES ;; *) echo "$0: error: invalid option \"$option\"" diff --git a/auto/os/conf b/auto/os/conf --- a/auto/os/conf +++ b/auto/os/conf @@ -54,3 +54,9 @@ if [ $TEST_BUILD_EPOLL = YES ]; then EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE" CORE_SRCS="$CORE_SRCS $EPOLL_SRCS" fi + +if [ $TEST_BUILD_SIGIO = YES ]; then + CFLAGS="$CFLAGS -D HAVE_SIGIO=1 -D TEST_BUILD_SIGIO=1" + EVENT_MODULES="$EVENT_MODULES $SIGIO_MODULE" + CORE_SRCS="$CORE_SRCS $SIGIO_SRCS" +fi diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -77,6 +77,9 @@ DEVPOLL_SRCS=src/event/modules/ngx_devpo EPOLL_MODULE="ngx_epoll_module" EPOLL_SRCS=src/event/modules/ngx_epoll_module.c +SIGIO_MODULE="ngx_sigio_module" +SIGIO_SRCS=src/event/modules/ngx_sigio_module.c + IOCP_MODULE="ngx_iocp_module" IOCP_SRCS=src/event/modules/ngx_iocp_module.c diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c @@ -357,6 +357,12 @@ int ngx_devpoll_process_events(ngx_log_t delta = ngx_elapsed_msec; ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; + if (err) { + ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, + log, err, "ioctl(DP_POLL) failed"); + return NGX_ERROR; + } + if ((int) timer != INFTIM) { delta = ngx_elapsed_msec - delta; @@ -370,12 +376,6 @@ int ngx_devpoll_process_events(ngx_log_t } } - if (err) { - ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, - log, err, "ioctl(DP_POLL) failed"); - return NGX_ERROR; - } - for (i = 0; i < events; i++) { c = &ngx_cycle->connections[event_list[i].fd]; diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -69,6 +69,8 @@ typedef struct { static int ngx_epoll_init(ngx_cycle_t *cycle); static void ngx_epoll_done(ngx_cycle_t *cycle); +static int ngx_epoll_add_event(ngx_event_t *ev, int event, u_int flags); +static int ngx_epoll_del_event(ngx_event_t *ev, int event, u_int flags); static int ngx_epoll_add_connection(ngx_connection_t *c); static int ngx_epoll_del_connection(ngx_connection_t *c); static int ngx_epoll_process_events(ngx_log_t *log); @@ -102,10 +104,10 @@ ngx_event_module_t ngx_epoll_module_ctx ngx_epoll_init_conf, /* init configuration */ { - NULL, /* add an event */ - NULL, /* delete an event */ - NULL, /* enable an event */ - NULL, /* disable an event */ + ngx_epoll_add_event, /* add an event */ + ngx_epoll_del_event, /* delete an event */ + ngx_epoll_add_event, /* enable an event */ + ngx_epoll_del_event, /* disable an event */ ngx_epoll_add_connection, /* add an connection */ ngx_epoll_del_connection, /* delete an connection */ ngx_epoll_process_events, /* process the events */ @@ -182,6 +184,70 @@ static void ngx_epoll_done(ngx_cycle_t * } +static int ngx_epoll_add_event(ngx_event_t *ev, int event, u_int flags) +{ + struct epoll_event e; + ngx_connection_t *c; + + c = ev->data; + +#if (NGX_READ_EVENT != EPOLLIN) || (NGX_WRITE_EVENT != EPOLLOUT) + if (event == NGX_READ_EVENT) { + event = EPOLLIN; + + } else { + event = EPOLLOUT; + } +#endif + + e.events = event; + e.data.ptr = (void *) ((uintptr_t) c | c->read->instance); + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "epoll add event: fd:%d ev:%04X", c->fd, e.events); + + if (epoll_ctl(ep, EPOLL_CTL_MOD, c->fd, &e) == -1) { + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, + "epoll_ctl(EPOLL_CTL_MOD, %d) failed", c->fd); + return NGX_ERROR; + } + + return NGX_OK; +} + + +static int ngx_epoll_del_event(ngx_event_t *ev, int event, u_int flags) +{ + struct epoll_event e; + ngx_connection_t *c; + + c = ev->data; + +#if (NGX_READ_EVENT != EPOLLIN) || (NGX_WRITE_EVENT != EPOLLOUT) + if (event == NGX_READ_EVENT) { + event = EPOLLIN; + + } else { + event = EPOLLOUT; + } +#endif + + e.events = event; + e.data.ptr = (void *) ((uintptr_t) c | c->read->instance); + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "epoll del event: fd:%d ev:%04X", c->fd, e.events); + + if (epoll_ctl(ep, EPOLL_CTL_MOD, c->fd, &e) == -1) { + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, + "epoll_ctl(EPOLL_CTL_MOD, %d) failed", c->fd); + return NGX_ERROR; + } + + return NGX_OK; +} + + static int ngx_epoll_add_connection(ngx_connection_t *c) { struct epoll_event ev; @@ -194,10 +260,13 @@ static int ngx_epoll_add_connection(ngx_ if (epoll_ctl(ep, EPOLL_CTL_ADD, c->fd, &ev) == -1) { ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, - "epoll_ctl(#%d) failed", c->fd); + "epoll_ctl(EPOLL_CTL_ADD, %d) failed", c->fd); return NGX_ERROR; } + c->read->active = 1; + c->write->active = 1; + return NGX_OK; } @@ -306,11 +375,19 @@ int ngx_epoll_process_events(ngx_log_t * c->write->event_handler(c->write); } - if (event_list[i].events & (EPOLLERR|EPOLLHUP|EPOLLMSG)) { - ngx_log_error(NGX_LOG_ERR, log, 0, + if (event_list[i].events & (EPOLLERR|EPOLLHUP)) { + ngx_log_error(NGX_LOG_ALERT, log, 0, "epoll_wait() error on fd:%d ev:%d", c->fd, event_list[i].events); + continue; } + + if (event_list[i].events & ~(EPOLLIN|EPOLLOUT)) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "epoll_wait() returned strange events on fd:%d ev:%d", + c->fd, event_list[i].events); + } + } if (timer != (ngx_msec_t) -1 && delta) { diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -378,6 +378,12 @@ static int ngx_kqueue_process_events(ngx delta = ngx_elapsed_msec; ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; + if (err) { + ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, + log, err, "kevent() failed"); + return NGX_ERROR; + } + if (timer) { delta = ngx_elapsed_msec - delta; @@ -392,12 +398,6 @@ static int ngx_kqueue_process_events(ngx } } - if (err) { - ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, - log, err, "kevent() failed"); - return NGX_ERROR; - } - for (i = 0; i < events; i++) { ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0, diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c @@ -247,14 +247,20 @@ static int ngx_poll_process_events(ngx_l err = 0; } - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "poll ready %d", ready); - ngx_gettimeofday(&tv); ngx_time_update(tv.tv_sec); delta = ngx_elapsed_msec; ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "poll ready %d", ready); + + if (err) { + ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, + log, err, "poll() failed"); + return NGX_ERROR; + } + if ((int) timer != INFTIM) { delta = ngx_elapsed_msec - delta; @@ -268,12 +274,6 @@ static int ngx_poll_process_events(ngx_l } } - if (err) { - ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, - log, err, "poll() failed"); - return NGX_ERROR; - } - nready = 0; for (i = 0; i < nevents && ready; i++) { diff --git a/src/event/modules/ngx_sigio_module.c b/src/event/modules/ngx_sigio_module.c --- a/src/event/modules/ngx_sigio_module.c +++ b/src/event/modules/ngx_sigio_module.c @@ -1,117 +1,356 @@ + +/* + * Copyright (C) 2002-2004 Igor Sysoev, http://sysoev.ru/en/ + */ + + +#include +#include +#include + + +#if (TEST_BUILD_SIGIO) + +#define F_SETSIG 10 + +#endif + + +typedef struct { + int signal; +} ngx_sigio_conf_t; + + +static int ngx_sigio_init(ngx_cycle_t *cycle); +static void ngx_sigio_done(ngx_cycle_t *cycle); +static int ngx_sigio_add_event(ngx_event_t *ev, int event, u_int flags); +static int ngx_sigio_del_event(ngx_event_t *ev, int event, u_int flags); +static int ngx_sigio_add_connection(ngx_connection_t *c); +static int ngx_sigio_del_connection(ngx_connection_t *c); +static int ngx_sigio_process_events(ngx_log_t *log); + +static void *ngx_sigio_create_conf(ngx_cycle_t *cycle); +static char *ngx_sigio_init_conf(ngx_cycle_t *cycle, void *conf); + + +static sigset_t set; + + +static ngx_str_t sigio_name = ngx_string("sigio"); + +static ngx_command_t ngx_sigio_commands[] = { + + {ngx_string("sigio_signal"), + NGX_EVENT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + 0, + offsetof(ngx_sigio_conf_t, signal), + NULL}, + + ngx_null_command +}; -int ngx_sigio_add_event(ngx_event_t *ev, int signal) +ngx_event_module_t ngx_sigio_module_ctx = { + &sigio_name, + ngx_sigio_create_conf, /* create configuration */ + ngx_sigio_init_conf, /* init configuration */ + + { + ngx_sigio_add_event, /* add an event */ + ngx_sigio_del_event, /* delete an event */ + ngx_sigio_add_event, /* enable an event */ + ngx_sigio_del_event, /* disable an event */ + ngx_sigio_add_connection, /* add an connection */ + ngx_sigio_del_connection, /* delete an connection */ + ngx_sigio_process_events, /* process the events */ + ngx_sigio_init, /* init the events */ + ngx_sigio_done, /* done the events */ + } + +}; + +ngx_module_t ngx_sigio_module = { + NGX_MODULE, + &ngx_sigio_module_ctx, /* module context */ + ngx_sigio_commands, /* module directives */ + NGX_EVENT_MODULE, /* module type */ + NULL, /* init module */ + NULL /* init child */ +}; + + +static int ngx_sigio_init(ngx_cycle_t *cycle) { - ngx_connection_t *c; + ngx_sigio_conf_t *sgcf; + + sgcf = ngx_event_get_conf(cycle->conf_ctx, ngx_sigio_module); + + sigemptyset(&set); + sigaddset(&set, sgcf->signal); + sigaddset(&set, SIGIO); + + if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "sigprocmask() failed"); + return NGX_ERROR; + } + + ngx_io = ngx_os_io; + + ngx_event_actions = ngx_sigio_module_ctx.actions; + + ngx_event_flags = NGX_USE_SIGIO_EVENT; + + return NGX_OK; +} + + +static void ngx_sigio_done(ngx_cycle_t *cycle) +{ +} + - c = (ngx_connection_t *) ev->data; +static int ngx_sigio_add_event(ngx_event_t *ev, int event, u_int flags) +{ + ngx_connection_t *c; + + c = ev->data; + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sigio add event: fd:%d ev:%04X", c->fd, event); + + return NGX_OK; +} + + +static int ngx_sigio_del_event(ngx_event_t *ev, int event, u_int flags) +{ + ngx_connection_t *c; + + c = ev->data; + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sigio del event: fd:%d ev:%04X", c->fd, event); + + return NGX_OK; +} + + +static int ngx_sigio_add_connection(ngx_connection_t *c) +{ + ngx_sigio_conf_t *sgcf; + + sgcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_sigio_module); + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sigio add connection: fd:%d signo:%d", c->fd, sgcf->signal); if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "fcntl(O_RDWR|O_NONBLOCK|O_ASYNC) failed"); return NGX_ERROR; } - if (fcntl(c->fd, F_SETSIG, signal) == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + if (fcntl(c->fd, F_SETSIG, sgcf->signal) == -1) { + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "fcntl(F_SETSIG) failed"); return NGX_ERROR; } - if (fcntl(c->fd, F_SETOWN, pid) == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + if (fcntl(c->fd, F_SETOWN, ngx_getpid()) == -1) { + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "fcntl(F_SETOWN) failed"); return NGX_ERROR; } #if (HAVE_ONESIGFD) if (fcntl(c->fd, F_SETAUXFL, O_ONESIGFD) == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "fcntl(F_SETAUXFL) failed"); return NGX_ERROR; } #endif + c->read->active = 1; + c->write->active = 1; + return NGX_OK; } + +static int ngx_sigio_del_connection(ngx_connection_t *c) +{ + c->read->active = 0; + c->write->active = 0; + + return NGX_OK; +} + + int ngx_sigio_process_events(ngx_log_t *log) { - struct siginfo si; - - for ( ;; ) { - if (timer) { - sig = sigtimedwait(&sigio_set, &si, &ts); + int signo; + ngx_int_t instance, i; + size_t n; + ngx_msec_t timer; + ngx_err_t err; + ngx_cycle_t **cycle; + siginfo_t si; + struct timeval tv; + struct timespec ts; + ngx_connection_t *c; + ngx_epoch_msec_t delta; + ngx_sigio_conf_t *sgcf; - if (sig == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, - "sigtimedwait() failed"); - continue; - } - } + timer = ngx_event_find_timer(); + ngx_old_elapsed_msec = ngx_elapsed_msec; + + if (timer) { + ts.tv_sec = timer / 1000; + ts.tv_nsec = (timer % 1000) * 1000000; + } - } else { - sig = sigwaitinfo(&set, &si); + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "sigio timer: %d", timer); + + if (timer) { + signo = sigtimedwait(&set, &si, &ts); + } else { + signo = sigwaitinfo(&set, &si); + } - if (sig == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, - "sigwaitinfo() failed"); - } - } + if (signo == -1) { + err = ngx_errno; + } else { + err = 0; + } + + ngx_gettimeofday(&tv); + ngx_time_update(tv.tv_sec); - if (sig == rtsig) { - c = &ngx_connections[si.si_fd]; + delta = ngx_elapsed_msec; + ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; + + if (err == -1) { + ngx_log_error(NGX_LOG_ALERT, c->log, err, + timer ? "sigtimedwait() failed" : "sigwaitinfo() failed"); + return NGX_ERROR; + } - if (si.si_band & (POLLERR|POLLHUP|POLLNVAL)) { - ev = ???; + if (timer) { + delta = ngx_elapsed_msec - delta; + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, + "sigio timer: %d, delta: %d", timer, (int) delta); + } + + sgcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_sigio_module); - if (ev->active) { - ev->ready = 1; - if (ev->event_handler(ev) == NGX_ERROR) { - ev->close_handler(ev); - } - } + if (signo == sgcf->signal) { + + /* STUB: old_cycles */ + c = &ngx_connections[si.si_fd]; + + if (si.si_band & EPOLLIN) { + if (!c->read->active) { + continue; } - if (si.si_band & (POLLIN)) { - ev = c->read; + c->read->ready = 1; + c->read->event_handler(c->read); + } + + } else if (signo == SIGIO) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "signal queue overflowed: " + "SIGIO, fd:%d, band:%d", si.si_fd, si.si_band); + + } else { + ngx_log_error(NGX_LOG_ALERT, log, 0, + timer ? "sigtimedwait() returned unexpected signal: %d": + "sigwaitinfo() returned unexpected signal: %d", + signo); + return NGX_ERROR; + } + } + + + + + - if (ev->active) { - ev->ready = 1; - if (ev->event_handler(ev) == NGX_ERROR) { - ev->close_handler(ev); - } - } + for (i = 0; i < events; i++) { + c = event_list[i].data.ptr; + + instance = (uintptr_t) c & 1; + c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1); + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0, + "sigio: fd:%d ev:%04X d:" PTR_FMT, + c->fd, event_list[i].events, event_list[i].data); + + if (c->read->instance != instance) { + + /* + * it's a stale event from a file descriptor + * that was just closed in this iteration + */ + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, + "sigio: stale event " PTR_FMT, c); + continue; + } + + if (event_list[i].events & EPOLLOUT) { + if (!c->write->active) { + continue; } - if (si.si_band & (POLLOUT)) { - ev = c->write; + c->write->ready = 1; + c->write->event_handler(c->write); + } + + if (event_list[i].events & (EPOLLERR|EPOLLHUP)) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "sigio_wait() error on fd:%d ev:%d", + c->fd, event_list[i].events); + continue; + } - if (ev->active) { - ev->ready = 1; - if (ev->event_handler(ev) == NGX_ERROR) { - ev->close_handler(ev); - } - } - } + if (event_list[i].events & ~(EPOLLIN|EPOLLOUT)) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "sigio_wait() returned strange events on fd:%d ev:%d", + c->fd, event_list[i].events); + } - } else if (sig == SIGIO) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, - "Signal queue overflowed: " - "SIGIO, fd:%d, band:%d", si.si_fd, si.si_band); + } + + if (timer != (ngx_msec_t) -1 && delta) { + ngx_event_expire_timers((ngx_msec_t) delta); + } - /* flush queue: method #1 (dphttpd) */ - ts.tv_sec = 0; - ts.tv_nsec = 0; - while (sigtimedwait(&sigio_set, &si, &ts) > 0); + return NGX_OK; +} + + +static void *ngx_sigio_create_conf(ngx_cycle_t *cycle) +{ + ngx_sigio_conf_t *sgcf; + + ngx_test_null(sgcf, ngx_palloc(cycle->pool, sizeof(ngx_sigio_conf_t)), + NGX_CONF_ERROR); + + sgcf->events = NGX_CONF_UNSET; - /* flush queue: method #2 (dkftpbench) */ - signal(m_signum, SIG_IGN); - signal(m_signum, SIG_DFL); + return epcf; +} + - /* do poll */ +static char *ngx_sigio_init_conf(ngx_cycle_t *cycle, void *conf) +{ + ngx_sigio_conf_t *sgcf = conf; - } else { - } - } + ngx_conf_init_unsigned_value(sgcf->signal, SIGRTMIN); + + return NGX_CONF_OK; }