[nginx] Win32: added WSAPoll() support.
Maxim Dounin
mdounin at mdounin.ru
Thu Jan 24 20:16:20 UTC 2019
details: https://hg.nginx.org/nginx/rev/4089b3d2cb59
branches:
changeset: 7444:4089b3d2cb59
user: Maxim Dounin <mdounin at mdounin.ru>
date: Thu Jan 24 21:51:21 2019 +0300
description:
Win32: added WSAPoll() support.
WSAPoll() is only available with Windows Vista and newer (and only
available during compilation if _WIN32_WINNT >= 0x0600). To make
sure the code works with Windows XP, we do not redefine _WIN32_WINNT,
but instead load WSAPoll() dynamically if it is not available during
compilation.
Also, sockets are not guaranteed to be small integers on Windows.
So an index array is used instead of NGX_USE_FD_EVENT to map
events to connections.
diffstat:
auto/os/win32 | 1 +
auto/sources | 1 +
src/event/modules/ngx_win32_poll_module.c | 74 +++++++++++++++++++-----------
src/os/win32/ngx_socket.h | 43 ++++++++++++++++++
src/os/win32/ngx_win32_init.c | 32 +++++++++++++
5 files changed, 124 insertions(+), 27 deletions(-)
diffs (322 lines):
diff --git a/auto/os/win32 b/auto/os/win32
--- a/auto/os/win32
+++ b/auto/os/win32
@@ -11,6 +11,7 @@ CORE_SRCS="$WIN32_SRCS $IOCP_SRCS"
OS_CONFIG="$WIN32_CONFIG"
NGX_ICONS="$NGX_WIN32_ICONS"
SELECT_SRCS=$WIN32_SELECT_SRCS
+POLL_SRCS=$WIN32_POLL_SRCS
ngx_pic_opt=
ngx_binext=".exe"
diff --git a/auto/sources b/auto/sources
--- a/auto/sources
+++ b/auto/sources
@@ -106,6 +106,7 @@ WIN32_SELECT_SRCS=src/event/modules/ngx_
POLL_MODULE=ngx_poll_module
POLL_SRCS=src/event/modules/ngx_poll_module.c
+WIN32_POLL_SRCS=src/event/modules/ngx_win32_poll_module.c
KQUEUE_MODULE=ngx_kqueue_module
KQUEUE_SRCS=src/event/modules/ngx_kqueue_module.c
diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_win32_poll_module.c
copy from src/event/modules/ngx_poll_module.c
copy to src/event/modules/ngx_win32_poll_module.c
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_win32_poll_module.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) Igor Sysoev
+ * Copyright (C) Maxim Dounin
* Copyright (C) Nginx, Inc.
*/
@@ -21,8 +22,9 @@ static ngx_int_t ngx_poll_process_events
static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);
-static struct pollfd *event_list;
-static ngx_uint_t nevents;
+static struct pollfd *event_list;
+static ngx_connection_t **event_index;
+static ngx_uint_t nevents;
static ngx_str_t poll_name = ngx_string("poll");
@@ -67,7 +69,8 @@ ngx_module_t ngx_poll_module = {
static ngx_int_t
ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{
- struct pollfd *list;
+ struct pollfd *list;
+ ngx_connection_t **index;
if (event_list == NULL) {
nevents = 0;
@@ -89,13 +92,27 @@ ngx_poll_init(ngx_cycle_t *cycle, ngx_ms
}
event_list = list;
+
+ index = ngx_alloc(sizeof(ngx_connection_t *) * cycle->connection_n,
+ cycle->log);
+ if (index == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (event_index) {
+ ngx_memcpy(index, event_index,
+ sizeof(ngx_connection_t *) * nevents);
+ ngx_free(event_index);
+ }
+
+ event_index = index;
}
ngx_io = ngx_os_io;
ngx_event_actions = ngx_poll_module_ctx.actions;
- ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_FD_EVENT;
+ ngx_event_flags = NGX_USE_LEVEL_EVENT;
return NGX_OK;
}
@@ -105,8 +122,10 @@ static void
ngx_poll_done(ngx_cycle_t *cycle)
{
ngx_free(event_list);
+ ngx_free(event_index);
event_list = NULL;
+ event_index = NULL;
}
@@ -143,10 +162,13 @@ ngx_poll_add_event(ngx_event_t *ev, ngx_
"poll add event: fd:%d ev:%i", c->fd, event);
if (e == NULL || e->index == NGX_INVALID_INDEX) {
+
event_list[nevents].fd = c->fd;
event_list[nevents].events = (short) event;
event_list[nevents].revents = 0;
+ event_index[nevents] = c;
+
ev->index = nevents;
nevents++;
@@ -204,10 +226,11 @@ ngx_poll_del_event(ngx_event_t *ev, ngx_
"index: copy event %ui to %i", nevents, ev->index);
event_list[ev->index] = event_list[nevents];
+ event_index[ev->index] = event_index[nevents];
- c = ngx_cycle->files[event_list[nevents].fd];
+ c = event_index[ev->index];
- if (c->fd == -1) {
+ if (c->fd == (ngx_socket_t) -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
"unexpected last event");
@@ -240,7 +263,7 @@ ngx_poll_process_events(ngx_cycle_t *cyc
{
int ready, revents;
ngx_err_t err;
- ngx_uint_t i, found, level;
+ ngx_uint_t i, found;
ngx_event_t *ev;
ngx_queue_t *queue;
ngx_connection_t *c;
@@ -259,7 +282,7 @@ ngx_poll_process_events(ngx_cycle_t *cyc
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "poll timer: %M", timer);
- ready = poll(event_list, (u_int) nevents, (int) timer);
+ ready = WSAPoll(event_list, (u_int) nevents, (int) timer);
err = (ready == -1) ? ngx_errno : 0;
@@ -271,20 +294,7 @@ ngx_poll_process_events(ngx_cycle_t *cyc
"poll ready %d of %ui", ready, nevents);
if (err) {
- if (err == NGX_EINTR) {
-
- if (ngx_event_timer_alarm) {
- ngx_event_timer_alarm = 0;
- return NGX_OK;
- }
-
- level = NGX_LOG_INFO;
-
- } else {
- level = NGX_LOG_ALERT;
- }
-
- ngx_log_error(level, cycle->log, err, "poll() failed");
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "WSAPoll() failed");
return NGX_ERROR;
}
@@ -294,7 +304,7 @@ ngx_poll_process_events(ngx_cycle_t *cyc
}
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
- "poll() returned no events without timeout");
+ "WSAPoll() returned no events without timeout");
return NGX_ERROR;
}
@@ -326,7 +336,7 @@ ngx_poll_process_events(ngx_cycle_t *cyc
event_list[i].fd, event_list[i].events, revents);
}
- if (event_list[i].fd == -1) {
+ if (event_list[i].fd == (ngx_socket_t) -1) {
/*
* the disabled event, a workaround for our possible bug,
* see the comment below
@@ -334,9 +344,9 @@ ngx_poll_process_events(ngx_cycle_t *cyc
continue;
}
- c = ngx_cycle->files[event_list[i].fd];
+ c = event_index[i];
- if (c->fd == -1) {
+ if (c->fd == (ngx_socket_t) -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");
/*
@@ -347,7 +357,7 @@ ngx_poll_process_events(ngx_cycle_t *cyc
if (i == nevents - 1) {
nevents--;
} else {
- event_list[i].fd = -1;
+ event_list[i].fd = (ngx_socket_t) -1;
}
continue;
@@ -411,5 +421,15 @@ ngx_poll_init_conf(ngx_cycle_t *cycle, v
return NGX_CONF_OK;
}
+#if (NGX_LOAD_WSAPOLL)
+
+ if (!ngx_have_wsapoll) {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+ "poll is not available on this platform");
+ return NGX_CONF_ERROR;
+ }
+
+#endif
+
return NGX_CONF_OK;
}
diff --git a/src/os/win32/ngx_socket.h b/src/os/win32/ngx_socket.h
--- a/src/os/win32/ngx_socket.h
+++ b/src/os/win32/ngx_socket.h
@@ -200,6 +200,49 @@ extern LPFN_CONNECTEX ngx_co
extern LPFN_DISCONNECTEX ngx_disconnectex;
+#if (NGX_HAVE_POLL && !defined POLLIN)
+
+/*
+ * WSAPoll() is only available if _WIN32_WINNT >= 0x0600.
+ * If it is not available during compilation, we try to
+ * load it dynamically at runtime.
+ */
+
+#define NGX_LOAD_WSAPOLL 1
+
+#define POLLRDNORM 0x0100
+#define POLLRDBAND 0x0200
+#define POLLIN (POLLRDNORM | POLLRDBAND)
+#define POLLPRI 0x0400
+
+#define POLLWRNORM 0x0010
+#define POLLOUT (POLLWRNORM)
+#define POLLWRBAND 0x0020
+
+#define POLLERR 0x0001
+#define POLLHUP 0x0002
+#define POLLNVAL 0x0004
+
+typedef struct pollfd {
+
+ SOCKET fd;
+ SHORT events;
+ SHORT revents;
+
+} WSAPOLLFD, *PWSAPOLLFD, FAR *LPWSAPOLLFD;
+
+typedef int (WSAAPI *ngx_wsapoll_pt)(
+ LPWSAPOLLFD fdArray,
+ ULONG fds,
+ INT timeout
+ );
+
+extern ngx_wsapoll_pt WSAPoll;
+extern ngx_uint_t ngx_have_wsapoll;
+
+#endif
+
+
int ngx_tcp_push(ngx_socket_t s);
#define ngx_tcp_push_n "tcp_push()"
diff --git a/src/os/win32/ngx_win32_init.c b/src/os/win32/ngx_win32_init.c
--- a/src/os/win32/ngx_win32_init.c
+++ b/src/os/win32/ngx_win32_init.c
@@ -58,6 +58,12 @@ static GUID cx_guid = WSAID_CONNECTEX;
static GUID dx_guid = WSAID_DISCONNECTEX;
+#if (NGX_LOAD_WSAPOLL)
+ngx_wsapoll_pt WSAPoll;
+ngx_uint_t ngx_have_wsapoll;
+#endif
+
+
ngx_int_t
ngx_os_init(ngx_log_t *log)
{
@@ -223,6 +229,32 @@ ngx_os_init(ngx_log_t *log)
ngx_close_socket_n " failed");
}
+#if (NGX_LOAD_WSAPOLL)
+ {
+ HMODULE hmod;
+
+ hmod = GetModuleHandle("ws2_32.dll");
+ if (hmod == NULL) {
+ ngx_log_error(NGX_LOG_NOTICE, log, ngx_errno,
+ "GetModuleHandle(\"ws2_32.dll\") failed");
+ goto nopoll;
+ }
+
+ WSAPoll = (ngx_wsapoll_pt) GetProcAddress(hmod, "WSAPoll");
+ if (WSAPoll == NULL) {
+ ngx_log_error(NGX_LOG_NOTICE, log, ngx_errno,
+ "GetProcAddress(\"WSAPoll\") failed");
+ goto nopoll;
+ }
+
+ ngx_have_wsapoll = 1;
+
+ }
+
+nopoll:
+
+#endif
+
if (GetEnvironmentVariable("ngx_unique", ngx_unique, NGX_INT32_LEN + 1)
!= 0)
{
More information about the nginx-devel
mailing list