# HG changeset patch # User Igor Sysoev # Date 1053523701 0 # Node ID 738fe44c70d51e242c35fb16a59a120309aa247b # Parent 19cc647ecd915de2df48259a3e9d19a9c2872017 nginx-0.0.1-2003-05-21-17:28:21 import diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -4,218 +4,59 @@ #include -/* - auto_conf - ngx_inline inline __inline __inline__ -*/ + +#if defined __FreeBSD__ +#include + + +#elif defined __linux__ +#include + -/* STUB */ + /* Solaris */ +#elif defined(sun) && (defined(__svr4__) || defined(__SVR4)) +#include + + +#elif defined _WIN32 + +/* STUB to allocate a big ngx_connections */ #undef FD_SETSIZE #define FD_SETSIZE 1024 - -/* auto_conf */ -#define NGX_ALIGN (4 - 1) -#define NGX_ALIGN_TYPE unsigned - -#define ngx_align(p) (char *) (((NGX_ALIGN_TYPE) p + NGX_ALIGN) & ~NGX_ALIGN) - - - -/* Platform specific: array[NGX_INVALID_ARRAY_INDEX] should cause SIGSEGV */ -#define NGX_INVALID_ARRAY_INDEX 0x80000000 +#include -#ifdef _WIN32 - -#define WIN32 1 - -#include -#include -#include /* offsetof */ -#include -#include - - -#define ngx_inline __inline - +#else /* posix */ -#ifndef HAVE_INHERITED_NONBLOCK -#define HAVE_INHERITED_NONBLOCK 1 #endif -#ifndef HAVE_WIN32_TRANSMITPACKETS -#define HAVE_WIN32_TRANSMITPACKETS 1 -#define HAVE_WIN32_TRANSMITFILE 0 -#endif - -#ifndef HAVE_WIN32_TRANSMITFILE -#define HAVE_WIN32_TRANSMITFILE 1 -#endif - -#if (HAVE_WIN32_TRANSMITPACKETS) || (HAVE_WIN32_TRANSMITFILE) -#define HAVE_SENDFILE 1 -#endif - -#else /* POSIX */ - -/* Solaris */ -#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) - -#define SOLARIS 1 - -#define _FILE_OFFSET_BITS 64 /* should be before sys/types.h */ - -#ifndef HAVE_INHERITED_NONBLOCK -#define HAVE_INHERITED_NONBLOCK 1 -#endif - -#include /* INFTIM */ - -#endif /* Solaris */ - +/* TODO: platform specific: array[NGX_INVALID_ARRAY_INDEX] must cause SIGSEGV */ +#define NGX_INVALID_ARRAY_INDEX 0x80000000 -#include -#include /* offsetof */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +/* TODO: auto_conf */ +#define NGX_ALIGN (4 - 1) +#define NGX_ALIGN_TYPE (unsigned int) + +#define ngx_align(p) (char *) ((NGX_ALIGN_TYPE p + NGX_ALIGN) & ~NGX_ALIGN) -#ifndef HAVE_POLL -#define HAVE_POLL 1 -#include +/* TODO: auto_conf: ngx_inline inline __inline __inline__ */ +#ifndef ngx_inline +#define ngx_inline inline #endif -#if (HAVE_DEVPOLL) && !(TEST_DEVPOLL) -#include -#include /* Solaris, HP/UX */ -#endif - - -#if (HAVE_AIO) -#include +#ifndef INADDR_NONE /* Solaris */ +#define INADDR_NONE ((unsigned long) -1) #endif - -#define ngx_inline inline - - -#endif /* POSIX */ - - - -#define LF 10 -#define CR 13 -#define CRLF "\x0d\x0a" - - #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 #endif -#if defined SO_ACCEPTFILTER || defined TCP_DEFER_ACCEPT - -#ifndef HAVE_DEFERRED_ACCEPT -#define HAVE_DEFERRED_ACCEPT 1 -#endif - -#endif - - -#ifndef HAVE_SELECT -#define HAVE_SELECT 1 -#endif - - -#ifdef __FreeBSD__ - -#include - -#ifndef HAVE_INHERITED_NONBLOCK -#define HAVE_INHERITED_NONBLOCK 1 -#endif - -/* FreeBSD sendfile */ -#if __FreeBSD_version >= 300007 - -#ifndef HAVE_FREEBSD_SENDFILE -#define HAVE_FREEBSD_SENDFILE 1 -#endif - -#ifndef HAVE_FREEBSD_SENDFILE_NBYTES_BUG -#define HAVE_FREEBSD_SENDFILE_NBYTES_BUG 2 -#endif - -#endif /* FreeBSD sendfile */ - -/* FreeBSD sendfile nbytes bug */ -#if (__FreeBSD__ == 4 && __FreeBSD_version >= 460100) \ - || __FreeBSD_version == 460001 \ - || __FreeBSD_version >= 500029 - -#if (HAVE_FREEBSD_SENDFILE_NBYTES_BUG == 2) -#undef HAVE_FREEBSD_SENDFILE_NBYTES_BUG -#define HAVE_FREEBSD_SENDFILE_NBYTES_BUG 0 -#endif - -#endif /* FreeBSD sendfile nbytes bug */ - -#if (HAVE_FREEBSD_SENDFILE) -#define HAVE_SENDFILE 1 -#endif - - -/* FreeBSD kqueue */ -#if (__FreeBSD__ == 4 && __FreeBSD_version >= 410000) \ - || __FreeBSD_version >= 500011 - -#ifndef HAVE_KQUEUE -#define HAVE_KQUEUE 1 -#include -#endif - -/* kqueue's NOTE_LOWAT */ -#if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \ - || __FreeBSD_version >= 500018 - -#ifndef HAVE_LOWAT_EVENT -#define HAVE_LOWAT_EVENT 1 -#endif - -#endif - -#endif /* FreeBSD kqueue */ - - -#endif /* __FreeBSD__ */ - - -#ifdef __SOME_OS_TEMPLATE__ - -#ifndef HAVE_INHERITED_NONBLOCK -#define HAVE_INHERITED_NONBLOCK 1 -#endif - -#endif - - #endif /* _NGX_CONFIG_H_INCLUDED_ */ diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -37,6 +37,12 @@ typedef struct ngx_event_s ngx_eve */ +#define LF 10 +#define CR 13 +#define CRLF "\x0d\x0a" + + + #define NGX_MAXHOSTNAMELEN 32 /* #define NGX_MAXHOSTNAMELEN MAXHOSTNAMELEN diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -81,7 +81,7 @@ ngx_log_debug(file->log, "temp fd: %d" _ if (ngx_create_path(file, path) == NGX_ERROR) { return NGX_ERROR; - } + } } } diff --git a/src/core/ngx_hunk.c b/src/core/ngx_hunk.c --- a/src/core/ngx_hunk.c +++ b/src/core/ngx_hunk.c @@ -25,9 +25,9 @@ ngx_hunk_t *ngx_create_temp_hunk(ngx_poo return h; } - + ngx_hunk_t *ngx_create_hunk_before(ngx_pool_t *pool, ngx_hunk_t *hunk, int size) -{ +{ ngx_hunk_t *h; ngx_test_null(h, ngx_palloc(pool, sizeof(ngx_hunk_t)), NULL); @@ -47,7 +47,7 @@ ngx_hunk_t *ngx_create_hunk_before(ngx_p } else { ngx_test_null(h->pre_start, ngx_palloc(pool, size), NULL); - h->start = h->pos = h->last = h->pre_start; + h->start = h->pos = h->last = h->pre_start; h->end = h->post_end = h->start + size; h->file_pos = h->file_last = 0; @@ -84,7 +84,7 @@ ngx_hunk_t *ngx_create_hunk_after(ngx_po } else { ngx_test_null(h->pre_start, ngx_palloc(pool, size), NULL); - h->start = h->pos = h->last = h->pre_start; + h->start = h->pos = h->last = h->pre_start; h->end = h->post_end = h->start + size; h->file_pos = h->file_last = 0; diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -147,7 +147,7 @@ void ngx_log_stderr(ngx_event_t *ev) n = read((ngx_fd_t) ev->data, errstr, sizeof(errstr - 1)); if (n == -1) { - err = ngx_errno; + err = ngx_errno; if (err == NGX_EAGAIN) { return; } diff --git a/src/core/ngx_modules.c b/src/core/ngx_modules.c --- a/src/core/ngx_modules.c +++ b/src/core/ngx_modules.c @@ -17,6 +17,9 @@ extern ngx_module_t ngx_kqueue_module; #if (HAVE_DEVPOLL) extern ngx_module_t ngx_devpoll_module; #endif +#if (HAVE_AIO) +extern ngx_module_t ngx_aio_module; +#endif extern ngx_module_t ngx_http_module; @@ -47,6 +50,9 @@ ngx_module_t *ngx_modules[] = { #if (HAVE_DEVPOLL) &ngx_devpoll_module, #endif +#if (HAVE_AIO) + &ngx_aio_module, +#endif /* http */ diff --git a/src/core/ngx_os_init.h b/src/core/ngx_os_init.h --- a/src/core/ngx_os_init.h +++ b/src/core/ngx_os_init.h @@ -4,23 +4,40 @@ #include #include -#if 0 -#include + + +#define NGX_IO_SENDFILE 1 +#define NGX_IO_ZEROCOPY 2 + +#if (HAVE_SENDFILE) +#define NGX_HAVE_SENDFILE NGX_IO_SENDFILE +#else +#define NGX_HAVE_SENDFILE 0 #endif +#if (HAVE_ZEROCOPY) +#define NGX_HAVE_ZEROCOPY NGX_IO_ZEROCOPY +#else +#define NGX_HAVE_ZEROCOPY 0 +#endif + + typedef struct { ssize_t (*recv)(ngx_connection_t *c, char *buf, size_t size); void *dummy_recv_chain; void *dummy_send; ngx_chain_t *(*send_chain)(ngx_connection_t *c, ngx_chain_t *in); + int flags; } ngx_os_io_t; int ngx_os_init(ngx_log_t *log); + extern ngx_os_io_t ngx_os_io; extern int ngx_max_sockets; +extern int ngx_inherited_nonblocking; #endif /* _NGX_OS_INIT_H_INCLUDED_ */ diff --git a/src/event/modules/ngx_aio_module.c b/src/event/modules/ngx_aio_module.c --- a/src/event/modules/ngx_aio_module.c +++ b/src/event/modules/ngx_aio_module.c @@ -1,39 +1,109 @@ #include - #include -#include -#include -#include #include -#include +#include #if (HAVE_KQUEUE) #include #endif -int ngx_aio_init(int max_connections, ngx_log_t *log) -{ +static int ngx_aio_init(ngx_log_t *log); +static void ngx_aio_done(ngx_log_t *log); +static int ngx_aio_add_event(ngx_event_t *ev, int event, u_int flags); +static int ngx_aio_del_event(ngx_event_t *ev, int event, u_int flags); +static int ngx_aio_process_events(ngx_log_t *log); + + +ngx_os_io_t ngx_os_aio = { + ngx_aio_read, + NULL, + ngx_aio_write, + ngx_aio_write_chain, + NGX_HAVE_ZEROCOPY +}; + + +static ngx_str_t aio_name = ngx_string("aio"); + +ngx_event_module_t ngx_aio_module_ctx = { + NGX_EVENT_MODULE, + &aio_name, + NULL, /* create configuration */ + NULL, /* init configuration */ + + { + ngx_aio_add_event, /* add an event */ + ngx_aio_del_event, /* delete an event */ + NULL, /* enable an event */ + NULL, /* disable an event */ + NULL, /* add an connection */ + NULL, /* delete an connection */ + ngx_aio_process_events, /* process the events */ + ngx_aio_init, /* init the events */ + ngx_aio_done /* done the events */ + } + +}; + +ngx_module_t ngx_aio_module = { + &ngx_aio_module_ctx, /* module context */ + 0, /* module index */ + NULL, /* module directives */ + NGX_EVENT_MODULE_TYPE, /* module type */ + NULL /* init module */ +}; + + + #if (HAVE_KQUEUE) - int rc; - - rc = ngx_kqueue_init(max_connections, log); +static int ngx_aio_init(ngx_log_t *log) +{ + if (ngx_kqueue_module_ctx.actions.init(log) == NGX_ERROR) { + return NGX_ERROR; + } ngx_event_flags = NGX_HAVE_AIO_EVENT|NGX_USE_AIO_EVENT; - ngx_write_chain_proc = ngx_aio_write_chain; + ngx_event_actions = ngx_aio_module_ctx.actions; + ngx_io = ngx_os_aio; - return rc; -#endif + return NGX_OK; } +static void ngx_aio_done(ngx_log_t *log) +{ + ngx_kqueue_module_ctx.actions.done(log); +} +/* The event adding and deleteing are needed for the listening sockets */ + +static int ngx_aio_add_event(ngx_event_t *ev, int event, u_int flags) +{ + return ngx_kqueue_module_ctx.actions.add(ev, event, flags); +} + + +static int ngx_aio_del_event(ngx_event_t *ev, int event, u_int flags) +{ + return ngx_kqueue_module_ctx.actions.del(ev, event, flags); +} + + +static int ngx_aio_process_events(ngx_log_t *log) +{ + return ngx_kqueue_module_ctx.actions.process(log); +} + +#endif + #if 0 + /* 1 */ int ngx_posix_aio_process_events(ngx_log_t *log) { @@ -66,6 +136,7 @@ int ngx_posix_aio_process_events(ngx_log /* 3 */ int ngx_posix_aio_process_events(ngx_log_t *log) { +#if 0 unmask signal /* BUG: AIO signal can be delivered before select() */ @@ -73,6 +144,9 @@ int ngx_posix_aio_process_events(ngx_log select(listen); mask signal +#endif + + pselect(listen, mask); if (ngx_socket_errno == NGX_EINTR) look ready array @@ -82,4 +156,5 @@ void aio_sig_handler(int signo, siginfo_ { push siginfo->si_value.sival_ptr } + #endif 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 @@ -10,7 +10,7 @@ #include -#if (TEST_DEVPOLL) +#if (TEST_BUILD_DEVPOLL) /* Solaris declarations */ 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 @@ -66,7 +66,7 @@ ngx_event_module_t ngx_kqueue_module_ct NULL, /* delete an connection */ ngx_kqueue_process_events, /* process the events */ ngx_kqueue_init, /* init the events */ - ngx_kqueue_done, /* done the events */ + ngx_kqueue_done /* done the events */ } }; @@ -343,22 +343,23 @@ static int ngx_kqueue_process_events(ngx } ev = (ngx_event_t *) event_list[i].udata; - instance = (uintptr_t) ev & 1; - ev = (void *) ((uintptr_t) ev & ~1); - - /* It's a stale event from a file descriptor - that was just closed in this iteration */ - - if (ev->active == 0 || ev->instance != instance) { - ngx_log_debug(log, "stale kevent"); - continue; - } switch (event_list[i].filter) { case EVFILT_READ: case EVFILT_WRITE: + instance = (uintptr_t) ev & 1; + ev = (void *) ((uintptr_t) ev & ~1); + + /* It's a stale event from a file descriptor + that was just closed in this iteration */ + + if (ev->active == 0 || ev->instance != instance) { + ngx_log_debug(log, "stale kevent"); + continue; + } + ev->available = event_list[i].data; if (event_list[i].flags & EV_EOF) { diff --git a/src/event/modules/ngx_kqueue_module.h b/src/event/modules/ngx_kqueue_module.h --- a/src/event/modules/ngx_kqueue_module.h +++ b/src/event/modules/ngx_kqueue_module.h @@ -9,6 +9,8 @@ typedef struct { extern int ngx_kqueue; +/* STUB */ extern ngx_event_module_t ngx_kqueue_module_ctx; + #endif /* _NGX_KQUEUE_MODULE_H_INCLUDED_ */ diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -31,7 +31,7 @@ extern ngx_event_module_t ngx_devpoll_mo static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy); -static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf); +static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, char *conf); static void *ngx_event_create_conf(ngx_pool_t *pool); static char *ngx_event_init_conf(ngx_pool_t *pool, void *conf); @@ -84,9 +84,9 @@ static ngx_command_t ngx_event_commands offsetof(ngx_event_conf_t, connections), NULL}, - {ngx_string("type"), + {ngx_string("use"), NGX_EVENT_CONF|NGX_CONF_TAKE1, - ngx_event_set_type, + ngx_event_use, 0, 0, NULL}, @@ -135,7 +135,7 @@ int ngx_pre_thread(ngx_array_t *ls, ngx_ ecf = ngx_event_get_conf(ngx_event_module_ctx); ngx_log_debug(log, "CONN: %d" _ ecf->connections); -ngx_log_debug(log, "TYPE: %d" _ ecf->type); +ngx_log_debug(log, "TYPE: %d" _ ecf->use); for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) { @@ -143,7 +143,7 @@ ngx_log_debug(log, "TYPE: %d" _ ecf->typ } module = ngx_modules[m]->ctx; - if (module->index == ecf->type) { + if (module->index == ecf->use) { if (module->actions.init(log) == NGX_ERROR) { return NGX_ERROR; } @@ -317,7 +317,7 @@ static char *ngx_events_block(ngx_conf_t } -static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf) +static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, char *conf) { ngx_event_conf_t *ecf = (ngx_event_conf_t *) conf; @@ -325,8 +325,8 @@ static char *ngx_event_set_type(ngx_conf ngx_str_t *args; ngx_event_module_t *module; - if (ecf->type != NGX_CONF_UNSET) { - return "duplicate event type" ; + if (ecf->use != NGX_CONF_UNSET) { + return "is duplicate" ; } args = cf->args->elts; @@ -339,7 +339,7 @@ static char *ngx_event_set_type(ngx_conf module = ngx_modules[m]->ctx; if (module->name->len == args[1].len) { if (ngx_strcmp(module->name->data, args[1].data) == 0) { - ecf->type = module->index; + ecf->use = module->index; return NGX_CONF_OK; } } @@ -358,7 +358,7 @@ static void *ngx_event_create_conf(ngx_p ecf->connections = NGX_CONF_UNSET; ecf->timer_queues = NGX_CONF_UNSET; - ecf->type = NGX_CONF_UNSET; + ecf->use = NGX_CONF_UNSET; return ecf; } @@ -380,19 +380,19 @@ static char *ngx_event_init_conf(ngx_poo #endif ngx_conf_init_value(ecf->connections, DEF_CONNECTIONS); - ngx_conf_init_value(ecf->type, ngx_kqueue_module_ctx.index); + ngx_conf_init_value(ecf->use, ngx_kqueue_module_ctx.index); #elif (HAVE_DEVPOLL) ngx_conf_init_value(ecf->connections, DEF_CONNECTIONS); - ngx_conf_init_value(ecf->type, ngx_devpoll_module_ctx.index); + ngx_conf_init_value(ecf->use, ngx_devpoll_module_ctx.index); #else /* HAVE_SELECT */ ngx_conf_init_value(ecf->connections, FD_SETSIZE < DEF_CONNECTIONS ? FD_SETSIZE : DEF_CONNECTIONS); - ngx_conf_init_value(ecf->type, ngx_select_module_ctx.index); + ngx_conf_init_value(ecf->use, ngx_select_module_ctx.index); #endif diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -327,7 +327,7 @@ extern int ngx_event_f typedef struct { int connections; int timer_queues; - int type; + int use; } ngx_event_conf_t; diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -65,39 +65,28 @@ void ngx_event_accept(ngx_event_t *ev) return; } - -#if (HAVE_INHERITED_NONBLOCK) + /* set a blocking mode for aio and non-blocking mode for others */ -#if (HAVE_AIO_EVENT) - if ((ngx_event_flags & NGX_HAVE_AIO_EVENT)) { - if (ngx_blocking(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno, - ngx_blocking_n " %s failed", ls->addr_text.data); - return; + if (ngx_inherited_nonblocking) { + if ((ngx_event_flags & NGX_USE_AIO_EVENT)) { + if (ngx_blocking(s) == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno, + ngx_blocking_n " %s failed", + ls->addr_text.data); + return; + } + } + + } else { + if ((ngx_event_flags & NGX_USE_AIO_EVENT) == 0) { + if (ngx_nonblocking(s) == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno, + ngx_nonblocking_n " %s failed", + ls->addr_text.data); + return; + } } } -#endif - -#else /* !HAVE_INHERITED_NONBLOCK */ - -#if (HAVE_AIO_EVENT) - if (!(ngx_event_flags & NGX_HAVE_AIO_EVENT)) { - if (ngx_nonblocking(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno, - ngx_nonblocking_n " %s failed", ls->addr_text.data); - return; - } - } -#else - if (ngx_nonblocking(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno, - ngx_nonblocking_n " %s failed", ls->addr_text.data); - return; - } -#endif - -#endif /* HAVE_INHERITED_NONBLOCK */ - rev = &ngx_read_events[s]; wev = &ngx_write_events[s]; @@ -130,15 +119,9 @@ void ngx_event_accept(ngx_event_t *ev) c->unexpected_eof = 1; wev->write = 1; -#if (USE_KQUEUE) - wev->ready = 1; -#else if ((ngx_event_flags & NGX_USE_AIO_EVENT) == 0) { wev->ready = 1; } -#endif - - /* STUB ? */ wev->timer = rev->timer = 10000; c->ctx = ls->ctx; c->servers = ls->servers; @@ -174,17 +157,10 @@ void ngx_event_accept(ngx_event_t *ev) ls->handler(c); -#if (USE_KQUEUE) - - ev->available--; - -#elif (HAVE_KQUEUE) - if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { ev->available--; } -#endif } while (ev->available); return; diff --git a/src/event/ngx_event_acceptex.c b/src/event/ngx_event_acceptex.c --- a/src/event/ngx_event_acceptex.c +++ b/src/event/ngx_event_acceptex.c @@ -29,6 +29,22 @@ int ngx_event_acceptex(ngx_event_t *ev) return NGX_OK; } +#if 0 + + /* can we do SO_UPDATE_ACCEPT_CONTEXT just before shutdown() ??? + or AcceptEx's context will be lost ??? */ + + /* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work */ + if (setsockopt(context->accept_socket, SOL_SOCKET, + SO_UPDATE_ACCEPT_CONTEXT, (char *)&nsd, + sizeof(nsd))) { + ap_log_error(APLOG_MARK, APLOG_ERR, WSAGetLastError(), server_conf, + "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed."); + + /* non fatal - we can not only do lingering close */ + +#endif + getacceptexsockaddrs(c->data, 0, c->socklen + 16, c->socklen + 16, &c->local_sockaddr, &c->local_socklen, diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -134,6 +134,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, send_timeout), NULL}, + {ngx_string("keepalive_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, keepalive_timeout), + NULL}, + {ngx_string("lingering_time"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -912,6 +919,7 @@ static void *ngx_http_core_create_loc_co lcf->send_timeout = NGX_CONF_UNSET; lcf->discarded_buffer_size = NGX_CONF_UNSET; + lcf->keepalive_timeout = NGX_CONF_UNSET; lcf->lingering_time = NGX_CONF_UNSET; lcf->lingering_timeout = NGX_CONF_UNSET; @@ -981,6 +989,8 @@ static char *ngx_http_core_merge_loc_con ngx_conf_merge_size_value(conf->discarded_buffer_size, prev->discarded_buffer_size, 1500); + ngx_conf_merge_msec_value(conf->keepalive_timeout, prev->keepalive_timeout, + 70000); ngx_conf_merge_msec_value(conf->lingering_time, prev->lingering_time, 30000); ngx_conf_merge_msec_value(conf->lingering_timeout, prev->lingering_timeout, diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -100,6 +100,7 @@ typedef struct { ngx_msec_t send_timeout; /* send_timeout */ size_t send_lowat; /* send_lowa */ size_t discarded_buffer_size; /* discarded_buffer_size */ + ngx_msec_t keepalive_timeout; /* keepalive_timeout */ ngx_msec_t lingering_time; /* lingering_time */ ngx_msec_t lingering_timeout; /* lingering_timeout */ diff --git a/src/http/ngx_http_event.c b/src/http/ngx_http_event.c --- a/src/http/ngx_http_event.c +++ b/src/http/ngx_http_event.c @@ -996,6 +996,7 @@ static void ngx_http_set_keepalive(ngx_h ngx_connection_t *c; ngx_http_log_ctx_t *ctx; ngx_http_core_main_conf_t *cmcf; + ngx_http_core_loc_conf_t *clcf; c = (ngx_connection_t *) r->connection; rev = c->read; @@ -1004,6 +1005,17 @@ static void ngx_http_set_keepalive(ngx_h ctx->action = "closing request"; ngx_http_close_request(r, 0); + if (rev->timer_set) { + ngx_del_timer(rev); + } else { + rev->timer_set = 1; + } + + clcf = (ngx_http_core_loc_conf_t *) + ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); + + ngx_add_timer(rev, clcf->keepalive_timeout); + if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { ngx_http_close_connection(c); diff --git a/src/os/unix/ngx_aio.h b/src/os/unix/ngx_aio.h new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_aio.h @@ -0,0 +1,13 @@ +#ifndef _NGX_AIO_H_INCLUDED_ +#define _NGX_AIO_H_INCLUDED_ + + +#include + + +ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size); +ssize_t ngx_aio_write(ngx_connection_t *c, char *buf, size_t size); +ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in); + + +#endif /* _NGX_AIO_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_aio_read.c b/src/os/unix/ngx_aio_read.c new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_aio_read.c @@ -0,0 +1,110 @@ + +#include +#include +#include + +#if (HAVE_KQUEUE) +#include +#endif + + +/* + The data is ready - 3 syscalls: + aio_read(), aio_error(), aio_return() + The data is not ready - 4 (kqueue) or 5 syscalls: + aio_read(), aio_error(), notifiction, + aio_error(), aio_return() + aio_cancel(), aio_error() +*/ + + +ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size) +{ + int rc, first, canceled; + ngx_event_t *ev; + + ev = c->read; + + canceled = 0; + + if (ev->timedout) { + ngx_set_socket_errno(NGX_ETIMEDOUT); + ngx_log_error(NGX_LOG_ERR, ev->log, 0, "aio_read() timed out"); + + rc = aio_cancel(c->fd, &ev->aiocb); + if (rc == -1) { + ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, + "aio_cancel() failed"); + return NGX_ERROR; + } + + ngx_log_debug(ev->log, "aio_cancel: %d" _ rc); + + canceled = 1; + + ev->ready = 1; + } + + first = 0; + + if (!ev->ready) { + ngx_memzero(&ev->aiocb, sizeof(struct aiocb)); + + ev->aiocb.aio_fildes = c->fd; + ev->aiocb.aio_buf = buf; + ev->aiocb.aio_nbytes = size; + +#if (HAVE_KQUEUE) + ev->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue; + ev->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT; + ev->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev; +#endif + + if (aio_read(&ev->aiocb) == -1) { + ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, + "aio_read() failed"); + return NGX_ERROR; + } + + ngx_log_debug(ev->log, "aio_read: OK"); + + ev->active = 1; + first = 1; + } + + ev->ready = 0; + + rc = aio_error(&ev->aiocb); + if (rc == -1) { + ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, "aio_error() failed"); + return NGX_ERROR; + } + + if (rc != 0) { + if (rc == NGX_EINPROGRESS) { + if (!first) { + ngx_log_error(NGX_LOG_CRIT, ev->log, rc, + "aio_read() still in progress"); + } + return NGX_AGAIN; + } + + if (rc == NGX_ECANCELED && canceled) { + return NGX_ERROR; + } + + ngx_log_error(NGX_LOG_CRIT, ev->log, rc, "aio_read() failed"); + return NGX_ERROR; + } + + rc = aio_return(&ev->aiocb); + if (rc == -1) { + ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, "aio_return() failed"); + + return NGX_ERROR; + } + + ngx_log_debug(ev->log, "aio_read: %d" _ rc); + + return rc; +} diff --git a/src/os/unix/ngx_aio_write.c b/src/os/unix/ngx_aio_write.c new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_aio_write.c @@ -0,0 +1,112 @@ + +#include +#include +#include + +#if (HAVE_KQUEUE) +#include +#endif + + +/* + The data is ready - 3 syscalls: + aio_write(), aio_error(), aio_return() + The data is not ready - 4 (kqueue) or 5 syscalls: + aio_write(), aio_error(), notifiction, + aio_error(), aio_return() + aio_cancel(), aio_error() +*/ + +ssize_t ngx_aio_write(ngx_connection_t *c, char *buf, size_t size) +{ + int rc, first, canceled; + ngx_event_t *ev; + + ev = c->write; + + canceled = 0; + +ngx_log_debug(ev->log, "aio: ev->ready: %d" _ ev->ready); +ngx_log_debug(ev->log, "aio: aiocb: %08x" _ &ev->aiocb); + + if (ev->timedout) { + ngx_set_socket_errno(NGX_ETIMEDOUT); + ngx_log_error(NGX_LOG_ERR, ev->log, 0, "aio_write() timed out"); + + rc = aio_cancel(c->fd, &ev->aiocb); + if (rc == -1) { + ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, + "aio_cancel() failed"); + return NGX_ERROR; + } + + ngx_log_debug(ev->log, "aio_cancel: %d" _ rc); + + canceled = 1; + + ev->ready = 1; + } + + first = 0; + + if (!ev->ready) { + ngx_memzero(&ev->aiocb, sizeof(struct aiocb)); + + ev->aiocb.aio_fildes = c->fd; + ev->aiocb.aio_buf = buf; + ev->aiocb.aio_nbytes = size; + +#if (HAVE_KQUEUE) + ev->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue; + ev->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT; + ev->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev; +#endif + + if (aio_write(&ev->aiocb) == -1) { + ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, + "aio_write() failed"); + return NGX_ERROR; + } + + ngx_log_debug(ev->log, "aio_write: OK"); + + ev->active = 1; + first = 1; + } + + ev->ready = 0; + + rc = aio_error(&ev->aiocb); + if (rc == -1) { + ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, "aio_error() failed"); + return NGX_ERROR; + } + + if (rc != 0) { + if (rc == NGX_EINPROGRESS) { + if (!first) { + ngx_log_error(NGX_LOG_CRIT, ev->log, rc, + "aio_write() still in progress"); + } + return NGX_AGAIN; + } + + if (rc == NGX_ECANCELED && canceled) { + return NGX_ERROR; + } + + ngx_log_error(NGX_LOG_CRIT, ev->log, rc, "aio_write() failed"); + return NGX_ERROR; + } + + rc = aio_return(&ev->aiocb); + if (rc == -1) { + ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, "aio_return() failed"); + + return NGX_ERROR; + } + + ngx_log_debug(ev->log, "aio_write: %d" _ rc); + + return rc; +} diff --git a/src/os/unix/ngx_aio_write_chain.c b/src/os/unix/ngx_aio_write_chain.c --- a/src/os/unix/ngx_aio_write_chain.c +++ b/src/os/unix/ngx_aio_write_chain.c @@ -1,14 +1,7 @@ #include - #include -#include -#include -#include -#include -#include -#include -#include +#include ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in) @@ -25,19 +18,19 @@ ngx_chain_t *ngx_aio_write_chain(ngx_con while (ce) { -ngx_log_debug(c->log, "aio_write ce: %x" _ ce->hunk->pos.mem); +ngx_log_debug(c->log, "aio_write ce: %x" _ ce->hunk->pos); - buf = prev = ce->hunk->pos.mem; + buf = prev = ce->hunk->pos; size = 0; /* coalesce the neighbouring chain entries */ - while (ce && prev == ce->hunk->pos.mem) { - size += ce->hunk->last.mem - ce->hunk->pos.mem; - prev = ce->hunk->last.mem; + while (ce && prev == ce->hunk->pos) { + size += ce->hunk->last - ce->hunk->pos; + prev = ce->hunk->last; ce = ce->next; } - rc = ngx_event_aio_write(c, buf, size); + rc = ngx_aio_write(c, buf, size); ngx_log_debug(c->log, "aio_write rc: %d" _ rc); @@ -62,27 +55,27 @@ ngx_log_debug(c->log, "aio_write rc: %d" #if (NGX_DEBUG_WRITE_CHAIN) ngx_log_debug(c->log, "write chain: %x %qx %qd" _ ce->hunk->type _ - ce->hunk->pos.file _ - ce->hunk->last.file - ce->hunk->pos.file); + ce->hunk->file_pos _ + ce->hunk->file_last - ce->hunk->file_pos); #endif - if (sent >= ce->hunk->last.file - ce->hunk->pos.file) { - sent -= ce->hunk->last.file - ce->hunk->pos.file; - ce->hunk->pos.file = ce->hunk->last.file; + if (sent >= ce->hunk->file_last - ce->hunk->file_pos) { + sent -= ce->hunk->file_last - ce->hunk->file_pos; + ce->hunk->file_pos = ce->hunk->file_last; #if (NGX_DEBUG_WRITE_CHAIN) ngx_log_debug(c->log, "write chain done: %qx %qd" _ - ce->hunk->pos.file _ sent); + ce->hunk->file_pos _ sent); #endif continue; } - ce->hunk->pos.file += sent; + ce->hunk->file_pos += sent; #if (NGX_DEBUG_WRITE_CHAIN) ngx_log_debug(c->log, "write chain rest: %qx %qd" _ - ce->hunk->pos.file _ - ce->hunk->last.file - ce->hunk->pos.file); + ce->hunk->file_pos _ + ce->hunk->file_last - ce->hunk->file_pos); #endif break; diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_freebsd_config.h @@ -0,0 +1,112 @@ +#ifndef _NGX_FREEBSD_CONFIG_H_INCLUDED_ +#define _NGX_FREEBSD_CONFIG_H_INCLUDED_ + + +#include +#include /* offsetof */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#ifndef HAVE_SELECT +#define HAVE_SELECT 1 +#endif + + +#ifndef HAVE_POLL +#define HAVE_POLL 1 +#endif +#if (HAVE_POLL) +#include +#endif + + /* FreeBSD aio supported via kqueue */ + +#if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \ + || __FreeBSD_version >= 500014 + +#ifndef HAVE_AIO +#define HAVE_AIO 1 +#endif + +#endif + +#if (HAVE_AIO) +#include +#endif + + +#if defined SO_ACCEPTFILTER && !defined HAVE_DEFERRED_ACCEPT +#define HAVE_DEFERRED_ACCEPT 1 +#endif + + + /* FreeBSD sendfile */ + +#if __FreeBSD_version >= 300007 + +#ifndef HAVE_FREEBSD_SENDFILE +#define HAVE_FREEBSD_SENDFILE 1 +#endif + +#endif + + +#if (HAVE_FREEBSD_SENDFILE) +#define HAVE_SENDFILE 1 +#endif + + + /* FreeBSD kqueue */ + +#if (__FreeBSD__ == 4 && __FreeBSD_version >= 410000) \ + || __FreeBSD_version >= 500011 + +#ifndef HAVE_KQUEUE +#define HAVE_KQUEUE 1 +#endif + +#endif + +#if (HAVE_KQUEUE) +#include +#endif + + + /* kqueue's NOTE_LOWAT */ + +#if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \ + || __FreeBSD_version >= 500018 + +#ifndef HAVE_LOWAT_EVENT +#define HAVE_LOWAT_EVENT 1 +#endif + +#endif + + + + +#ifndef HAVE_INHERITED_NONBLOCK +#define HAVE_INHERITED_NONBLOCK 1 +#endif + + +#endif /* _NGX_FREEBSD_CONFIG_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c --- a/src/os/unix/ngx_freebsd_init.c +++ b/src/os/unix/ngx_freebsd_init.c @@ -12,9 +12,10 @@ int ngx_freebsd_sendfile_nbytes_bug; ngx_os_io_t ngx_os_io = { ngx_unix_recv, - NULL, + ngx_readv_chain, NULL, - ngx_freebsd_write_chain + ngx_freebsd_write_chain, + NGX_HAVE_SENDFILE|NGX_HAVE_ZEROCOPY }; @@ -107,5 +108,5 @@ int ngx_os_init(ngx_log_t *log) ngx_log_error(NGX_LOG_INFO, log, 0, "net.inet.tcp.sendspace: %d", ngx_freebsd_net_inet_tcp_sendspace); - return ngx_unix_init(log); + return ngx_posix_init(log); } diff --git a/src/os/unix/ngx_freebsd_init.h b/src/os/unix/ngx_freebsd_init.h --- a/src/os/unix/ngx_freebsd_init.h +++ b/src/os/unix/ngx_freebsd_init.h @@ -7,8 +7,11 @@ #include -int ngx_unix_init(ngx_log_t *log); +/* STUB */ +int ngx_posix_init(ngx_log_t *log); ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size); +ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry); +/* */ extern int ngx_freebsd_kern_osreldate; diff --git a/src/os/unix/ngx_freebsd_rfork_thread.c b/src/os/unix/ngx_freebsd_rfork_thread.c --- a/src/os/unix/ngx_freebsd_rfork_thread.c +++ b/src/os/unix/ngx_freebsd_rfork_thread.c @@ -168,7 +168,7 @@ ngx_tid_t ngx_thread_self() static inline int ngx_gettid() -{ +{ char *sp; if (stack_size == 0) { diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_linux_config.h @@ -0,0 +1,48 @@ +#ifndef _NGX_LINUX_CONFIG_H_INCLUDED_ +#define _NGX_LINUX_CONFIG_H_INCLUDED_ + + +#include +#include /* offsetof */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef HAVE_SELECT +#define HAVE_SELECT 1 +#endif + + +#ifndef HAVE_POLL +#define HAVE_POLL 1 +#endif +#if (HAVE_POLL) +#include +#endif + + +#if defined TCP_DEFER_ACCEPT && !defined HAVE_DEFERRED_ACCEPT +#define HAVE_DEFERRED_ACCEPT 1 +#endif + + +#ifndef HAVE_INHERITED_NONBLOCK +#define HAVE_INHERITED_NONBLOCK 1 +#endif + + +#endif /* _NGX_LINUX_CONFIG_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_posix_init.c @@ -0,0 +1,70 @@ + +#include +#include + + +int ngx_max_sockets; +int ngx_inherited_nonblocking; + + +int ngx_posix_init(ngx_log_t *log) +{ + struct sigaction sa; + struct rlimit rlmt; + + ngx_memzero(&sa, sizeof(struct sigaction)); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + + if (sigaction(SIGPIPE, &sa, NULL) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + "sigaction(SIGPIPE, SIG_IGN) failed"); + return NGX_ERROR; + } + + + if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, errno, + "getrlimit(RLIMIT_NOFILE) failed)"); + return NGX_ERROR; + } + + ngx_log_error(NGX_LOG_INFO, log, 0, + "getrlimit(RLIMIT_NOFILE): %qd:%qd", + rlmt.rlim_cur, rlmt.rlim_max); + + ngx_max_sockets = rlmt.rlim_cur; + +#if (HAVE_INHERITED_NONBLOCK) + ngx_inherited_nonblocking = 1; +#else + ngx_inherited_nonblocking = 0; +#endif + + return NGX_OK; +} + + +int ngx_posix_post_conf_init(ngx_log_t *log) +{ + ngx_fd_t pp[2]; + + if (pipe(pp) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "pipe() failed"); + return NGX_ERROR; + } + + if (dup2(pp[1], STDERR_FILENO) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, errno, "dup2(STDERR) failed"); + return NGX_ERROR; + } + + if (pp[1] > STDERR_FILENO) { + if (close(pp[1]) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, errno, "close() failed"); + return NGX_ERROR; + } + } + + return NGX_OK; +} diff --git a/src/os/unix/ngx_recv_chain.c b/src/os/unix/ngx_readv_chain.c rename from src/os/unix/ngx_recv_chain.c rename to src/os/unix/ngx_readv_chain.c --- a/src/os/unix/ngx_recv_chain.c +++ b/src/os/unix/ngx_readv_chain.c @@ -1,12 +1,9 @@ #include #include -#include -#include -#include -ssize_t ngx_recv_chain(ngx_connection_t *c, ngx_chain_t *entry) +ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry) { ssize_t n; struct iovec *iov; diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -17,7 +17,7 @@ ssize_t ngx_unix_recv(ngx_connection_t * #if (HAVE_KQUEUE) /* DEBUG */ if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { - ngx_log_debug(c->log, "ngx_recv: eof:%d, avail:%d, err:%d" _ + ngx_log_debug(c->log, "recv: eof:%d, avail:%d, err:%d" _ ev->eof _ ev->available _ ev->error); } #endif @@ -38,7 +38,7 @@ ssize_t ngx_unix_recv(ngx_connection_t * } else { n = recv(c->fd, buf, size, 0); -ngx_log_debug(c->log, "ngx_recv: read:%d:%d" _ n _ size); +ngx_log_debug(c->log, "recv: read:%d:%d" _ n _ size); if (n == -1) { err = ngx_socket_errno; @@ -49,6 +49,8 @@ ngx_log_debug(c->log, "ngx_recv: read:%d n = recv(c->fd, buf, size, 0); +ngx_log_debug(c->log, "recv: read:%d:%d" _ n _ size); + if (n == -1) { err = ngx_socket_errno; } diff --git a/src/os/unix/ngx_socket.c b/src/os/unix/ngx_socket.c --- a/src/os/unix/ngx_socket.c +++ b/src/os/unix/ngx_socket.c @@ -2,12 +2,15 @@ #include -/* ioctl(FIONBIO) set blocking mode with one syscall only while +/* + ioctl(FIONBIO) set blocking mode with one syscall only while fcntl(F_SETFL, ~O_NONBLOCK) need to know previous state using fcntl(F_GETFL). - On FreeBSD both are syscall */ -#ifdef __FreeBSD__ + ioctl() and fcntl() are syscalls on FreeBSD, Solaris 7/8 and Linux +*/ + +#if 1 int ngx_nonblocking(ngx_socket_t s) { diff --git a/src/os/unix/ngx_socket.h b/src/os/unix/ngx_socket.h --- a/src/os/unix/ngx_socket.h +++ b/src/os/unix/ngx_socket.h @@ -4,10 +4,6 @@ #include -#ifdef __FreeBSD__ -#include -#endif - #define NGX_WRITE_SHUTDOWN SHUT_WR @@ -17,7 +13,7 @@ typedef int ngx_socket_t; #define ngx_socket_n "socket()" -#ifdef __FreeBSD__ +#if 1 int ngx_nonblocking(ngx_socket_t s); int ngx_blocking(ngx_socket_t s); diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_solaris_config.h @@ -0,0 +1,64 @@ +#ifndef _NGX_SOLARIS_CONFIG_H_INCLUDED_ +#define _NGX_SOLARIS_CONFIG_H_INCLUDED_ + + +#define SOLARIS 1 + +#define _FILE_OFFSET_BITS 64 /* must be before sys/types.h */ + +#include +#include /* offsetof */ +#include +#include +#include +#include +#include +#include +#include +#include /* bzero() */ +#include +#include /* FIONBIO */ +#include /* INFTIM */ +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef uint32_t u_int32_t; + + +#ifndef HAVE_SELECT +#define HAVE_SELECT 1 +#endif + + +#ifndef HAVE_POLL +#define HAVE_POLL 1 +#endif +#if (HAVE_POLL) +#include +#endif + + +#if (HAVE_AIO) +#include +#endif + + +#if (HAVE_DEVPOLL) +#include +#include +#endif + + +#ifndef HAVE_INHERITED_NONBLOCK +#define HAVE_INHERITED_NONBLOCK 1 +#endif + + +#endif /* _NGX_SOLARIS_CONFIG_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_unix_init.c b/src/os/unix/ngx_unix_init.c --- a/src/os/unix/ngx_unix_init.c +++ b/src/os/unix/ngx_unix_init.c @@ -3,61 +3,30 @@ #include -int ngx_max_sockets; +/* STUB */ +ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size); +ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in); +int ngx_posix_init(ngx_log_t *log); +int ngx_posix_post_conf_init(ngx_log_t *log); +/* */ -int ngx_unix_init(ngx_log_t *log) -{ - struct sigaction sa; - struct rlimit rlmt; - - ngx_memzero(&sa, sizeof(struct sigaction)); - sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); - - if (sigaction(SIGPIPE, &sa, NULL) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - "sigaction(SIGPIPE, SIG_IGN) failed"); - return NGX_ERROR; - } +ngx_os_io_t ngx_os_io = { + ngx_unix_recv, + NULL, + NULL, + ngx_writev_chain, + NGX_HAVE_ZEROCOPY +}; - if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { - ngx_log_error(NGX_LOG_ALERT, log, errno, - "getrlimit(RLIMIT_NOFILE) failed)"); - return NGX_ERROR; - } - - ngx_log_error(NGX_LOG_INFO, log, 0, - "getrlimit(RLIMIT_NOFILE): %qd:%qd", - rlmt.rlim_cur, rlmt.rlim_max); - - ngx_max_sockets = rlmt.rlim_cur; - - return NGX_OK; +int ngx_os_init(ngx_log_t *log) +{ + return ngx_posix_init(log); } -int ngx_unix_post_conf_init(ngx_log_t *log) +int ngx_os_post_conf_init(ngx_log_t *log) { - ngx_fd_t pp[2]; - - if (pipe(pp) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "pipe() failed"); - return NGX_ERROR; - } - - if (dup2(pp[1], STDERR_FILENO) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, errno, "dup2(STDERR) failed"); - return NGX_ERROR; - } - - if (pp[1] > STDERR_FILENO) { - if (close(pp[1]) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, errno, "close() failed"); - return NGX_ERROR; - } - } - - return NGX_OK; + return ngx_posix_post_conf_init(log); } diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_writev_chain.c @@ -0,0 +1,93 @@ + +#include +#include + + +ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in) +{ + char *prev; + size_t size; + ssize_t n; + off_t sent; + struct iovec *iov; + ngx_err_t err; + ngx_array_t io; + ngx_chain_t *ce; + + ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR); + + prev = NULL; + iov = NULL; + + /* create the iovec and coalesce the neighbouring chain entries */ + for (ce = in; ce; ce = ce->next) { + + if (prev == ce->hunk->pos) { + iov->iov_len += ce->hunk->last - ce->hunk->pos; + prev = ce->hunk->last; + + } else { + ngx_test_null(iov, ngx_push_array(&io), NGX_CHAIN_ERROR); + iov->iov_base = ce->hunk->pos; + iov->iov_len = ce->hunk->last - ce->hunk->pos; + prev = ce->hunk->last; + } + } + + n = writev(c->fd, (struct iovec *) io.elts, io.nelts); + + if (n == -1) { + err = ngx_errno; + if (err == NGX_EAGAIN) { + ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN"); + + } else if (err == NGX_EINTR) { + ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR"); + + } else { + ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed"); + return NGX_CHAIN_ERROR; + } + } + + sent = n > 0 ? n : 0; + +#if (NGX_DEBUG_WRITE_CHAIN) + ngx_log_debug(c->log, "writev: %qd" _ sent); +#endif + + c->sent += sent; + + for (ce = in; ce && sent > 0; ce = ce->next) { + + size = ce->hunk->last - ce->hunk->pos; + + if (sent >= size) { + sent -= size; + + if (ce->hunk->type & NGX_HUNK_IN_MEMORY) { + ce->hunk->pos = ce->hunk->last; + } + + if (ce->hunk->type & NGX_HUNK_FILE) { + ce->hunk->file_pos = ce->hunk->file_last; + } + + continue; + } + + if (ce->hunk->type & NGX_HUNK_IN_MEMORY) { + ce->hunk->pos += sent; + } + + if (ce->hunk->type & NGX_HUNK_FILE) { + ce->hunk->file_pos += sent; + } + + break; + } + + ngx_destroy_array(&io); + + return ce; +} diff --git a/src/os/win32/ngx_init.c b/src/os/win32/ngx_init.c --- a/src/os/win32/ngx_init.c +++ b/src/os/win32/ngx_init.c @@ -7,17 +7,10 @@ int ngx_max_sockets; ngx_os_io_t ngx_os_io = { -#if 0 - ngx_unix_recv, - NULL, - NULL, - ngx_freebsd_write_chain -#else - NULL, + ngx_wsarecv, NULL, NULL, NULL -#endif }; diff --git a/src/os/win32/ngx_recv.c b/src/os/win32/ngx_recv.c new file mode 100644 --- /dev/null +++ b/src/os/win32/ngx_recv.c @@ -0,0 +1,93 @@ + +#include +#include +#include + + +ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size) +{ + int rc; + u_int flags; + size_t bytes; + ngx_err_t err; + WSABUF wsabuf[1]; + ngx_event_t *ev; + LPWSAOVERLAPPED_COMPLETION_ROUTINE handler; + + ev = c->read; + +/* DEBUG */ bytes = 0; + + if (ev->timedout) { + ngx_set_socket_errno(NGX_ETIMEDOUT); + ngx_log_error(NGX_LOG_ERR, ev->log, 0, "WSARecv() timed out"); + + return NGX_ERROR; + } + + if (ev->ready) { + ev->ready = 0; + +#if (HAVE_IOCP_EVENT) /* iocp */ + + if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) { + if (ev->ovlp.error) { + ngx_log_error(NGX_LOG_ERR, c->log, ev->ovlp.error, + "WSARecv() failed"); + return NGX_ERROR; + } + + return ev->available; + } + +#endif + + if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &ev->ovlp, + &bytes, 0, NULL) == 0) { + err = ngx_socket_errno; + ngx_log_error(NGX_LOG_CRIT, ev->log, err, + "WSARecv() or WSAGetOverlappedResult() failed"); + + return NGX_ERROR; + } + + return bytes; + } + + ngx_memzero(&ev->ovlp, sizeof(WSAOVERLAPPED)); + wsabuf[0].buf = buf; + wsabuf[0].len = size; + flags = 0; + +#if 0 + handler = ev->handler; +#else + handler = NULL; +#endif + + rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, + (LPWSAOVERLAPPED) &ev->ovlp, handler); + + ngx_log_debug(ev->log, "WSARecv: %d:%d" _ rc _ bytes); + + if (rc == -1) { + err = ngx_socket_errno; + if (err == WSA_IO_PENDING) { + return NGX_AGAIN; + + } else { + ngx_log_error(NGX_LOG_CRIT, ev->log, err, "WSARecv() failed"); + return NGX_ERROR; + } + } + +#if (HAVE_IOCP_EVENT) /* iocp */ + + if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) { + return NGX_AGAIN; + } + +#endif + + return bytes; +} diff --git a/src/os/win32/ngx_win32_config.h b/src/os/win32/ngx_win32_config.h new file mode 100644 --- /dev/null +++ b/src/os/win32/ngx_win32_config.h @@ -0,0 +1,35 @@ +#ifndef _NGX_WIN32_CONFIG_H_INCLUDED_ +#define _NGX_WIN32_CONFIG_H_INCLUDED_ + + +#define WIN32 1 + +#include +#include +#include /* offsetof */ +#include +#include + + +#define ngx_inline __inline + + +#ifndef HAVE_INHERITED_NONBLOCK +#define HAVE_INHERITED_NONBLOCK 1 +#endif + +#ifndef HAVE_WIN32_TRANSMITPACKETS +#define HAVE_WIN32_TRANSMITPACKETS 1 +#define HAVE_WIN32_TRANSMITFILE 0 +#endif + +#ifndef HAVE_WIN32_TRANSMITFILE +#define HAVE_WIN32_TRANSMITFILE 1 +#endif + +#if (HAVE_WIN32_TRANSMITPACKETS) || (HAVE_WIN32_TRANSMITFILE) +#define HAVE_SENDFILE 1 +#endif + + +#endif /* _NGX_WIN32_CONFIG_H_INCLUDED_ */