diff src/event/modules/ngx_devpoll_module.c @ 332:3a91bfeffaba NGINX_0_6_10

nginx 0.6.10 *) Feature: the "open_file_cache", "open_file_cache_retest", and "open_file_cache_errors" directives. *) Bugfix: socket leak; bug appeared in 0.6.7. *) Bugfix: a charset set by the "charset" directive was not appended to the "Content-Type" header set by $r->send_http_header(). *) Bugfix: a segmentation fault might occur in worker process if /dev/poll method was used.
author Igor Sysoev <http://sysoev.ru>
date Mon, 03 Sep 2007 00:00:00 +0400
parents f7cd062ee035
children f39b9e29530d
line wrap: on
line diff
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -13,8 +13,9 @@
 
 /* Solaris declarations */
 
-#define POLLREMOVE  0x0800
-#define DP_POLL     0xD001
+#define POLLREMOVE   0x0800
+#define DP_POLL      0xD001
+#define DP_ISPOLLED  0xD002
 
 struct dvpoll {
     struct pollfd  *dp_fds;
@@ -255,10 +256,16 @@ ngx_devpoll_del_event(ngx_event_t *ev, n
     ev->active = 0;
 
     if (flags & NGX_CLOSE_EVENT) {
+        e = (event == POLLIN) ? c->write : c->read;
+
+        if (e) {
+            e->active = 0;
+        }
+
         return NGX_OK;
     }
 
-    /* restore the paired event if it exists */
+    /* restore the pair event if it exists */
 
     if (event == POLLIN) {
         e = c->write;
@@ -330,13 +337,15 @@ ngx_int_t
 ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
     ngx_uint_t flags)
 {
-    int                 events, revents;
+    int                 events, revents, rc;
     size_t              n;
+    ngx_fd_t            fd;
     ngx_err_t           err;
     ngx_int_t           i;
     ngx_uint_t          level;
     ngx_event_t        *rev, *wev, **queue;
     ngx_connection_t   *c;
+    struct pollfd       pfd;
     struct dvpoll       dvp;
 
     /* NGX_TIMER_INFINITE == INFTIM */
@@ -401,34 +410,77 @@ ngx_devpoll_process_events(ngx_cycle_t *
     ngx_mutex_lock(ngx_posted_events_mutex);
 
     for (i = 0; i < events; i++) {
-        c = ngx_cycle->files[event_list[i].fd];
+
+        fd = event_list[i].fd;
+        revents = event_list[i].revents;
+
+        c = ngx_cycle->files[fd];
+
+        if (c == NULL || c->fd == -1) {
+
+            pfd.fd = fd;
+            pfd.events = 0;
+            pfd.revents = 0;
+
+            rc = ioctl(dp, DP_ISPOLLED, &pfd);
+
+            switch (rc) {
+
+            case -1:
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                    "ioctl(DP_ISPOLLED) failed for socket %d, event",
+                    fd, revents);
+                break;
 
-        if (c->fd == -1) {
-            if (c->read->closed) {
-                continue;
+            case 0:
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+                    "phantom event %04Xd for closed and removed socket %d",
+                    revents, fd);
+                break;
+
+            default:
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+                    "unexpected event %04Xd for closed and removed socket %d, ",
+                    "ioctl(DP_ISPOLLED) returned rc:%d, fd:%d, event %04Xd",
+                    revents, fd, rc, pfd.fd, pfd.revents);
+
+                pfd.fd = fd;
+                pfd.events = POLLREMOVE;
+                pfd.revents = 0;
+
+                if (write(dp, &pfd, sizeof(struct pollfd))
+                    != (ssize_t) sizeof(struct pollfd))
+                {
+                    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                                  "write(/dev/poll) for %d failed, fd");
+                }
+
+                if (close(fd) == -1) {
+                    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                                  "close(%d) failed", fd);
+                }
+
+                break;
             }
 
-            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");
             continue;
         }
 
-        revents = event_list[i].revents;
-
         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                        "devpoll: fd:%d, ev:%04Xd, rev:%04Xd",
-                       event_list[i].fd, event_list[i].events, revents);
+                       fd, event_list[i].events, revents);
 
         if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "ioctl(DP_POLL) error fd:%d ev:%04Xd rev:%04Xd",
-                          event_list[i].fd, event_list[i].events, revents);
+                          fd, event_list[i].events, revents);
         }
 
         if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                           "strange ioctl(DP_POLL) events "
                           "fd:%d ev:%04Xd rev:%04Xd",
-                          event_list[i].fd, event_list[i].events, revents);
+                          fd, event_list[i].events, revents);
         }
 
         if ((revents & (POLLERR|POLLHUP|POLLNVAL))