diff src/event/modules/ngx_win32_poll_module.c @ 7444:4089b3d2cb59

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.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 24 Jan 2019 21:51:21 +0300
parents src/event/modules/ngx_poll_module.c@e0e636ab10be
children efd71d49bde0
line wrap: on
line diff
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;
 }