1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_event.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
14e18a033bSKonstantin Ananyevstatic void ngx_poll_done(ngx_cycle_t *cycle);
15e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event,
16e18a033bSKonstantin Ananyev    ngx_uint_t flags);
17e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event,
18e18a033bSKonstantin Ananyev    ngx_uint_t flags);
19e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
20e18a033bSKonstantin Ananyev    ngx_uint_t flags);
21e18a033bSKonstantin Ananyevstatic char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);
22e18a033bSKonstantin Ananyev
23e18a033bSKonstantin Ananyev
24e18a033bSKonstantin Ananyevstatic struct pollfd  *event_list;
25e18a033bSKonstantin Ananyevstatic ngx_uint_t      nevents;
26e18a033bSKonstantin Ananyev
27e18a033bSKonstantin Ananyev
28e18a033bSKonstantin Ananyevstatic ngx_str_t           poll_name = ngx_string("poll");
29e18a033bSKonstantin Ananyev
30e18a033bSKonstantin Ananyevstatic ngx_event_module_t  ngx_poll_module_ctx = {
31e18a033bSKonstantin Ananyev    &poll_name,
32e18a033bSKonstantin Ananyev    NULL,                                  /* create configuration */
33e18a033bSKonstantin Ananyev    ngx_poll_init_conf,                    /* init configuration */
34e18a033bSKonstantin Ananyev
35e18a033bSKonstantin Ananyev    {
36e18a033bSKonstantin Ananyev        ngx_poll_add_event,                /* add an event */
37e18a033bSKonstantin Ananyev        ngx_poll_del_event,                /* delete an event */
38e18a033bSKonstantin Ananyev        ngx_poll_add_event,                /* enable an event */
39e18a033bSKonstantin Ananyev        ngx_poll_del_event,                /* disable an event */
40e18a033bSKonstantin Ananyev        NULL,                              /* add an connection */
41e18a033bSKonstantin Ananyev        NULL,                              /* delete an connection */
42e18a033bSKonstantin Ananyev        NULL,                              /* trigger a notify */
43e18a033bSKonstantin Ananyev        ngx_poll_process_events,           /* process the events */
44e18a033bSKonstantin Ananyev        ngx_poll_init,                     /* init the events */
45e18a033bSKonstantin Ananyev        ngx_poll_done                      /* done the events */
46e18a033bSKonstantin Ananyev    }
47e18a033bSKonstantin Ananyev
48e18a033bSKonstantin Ananyev};
49e18a033bSKonstantin Ananyev
50e18a033bSKonstantin Ananyevngx_module_t  ngx_poll_module = {
51e18a033bSKonstantin Ananyev    NGX_MODULE_V1,
52e18a033bSKonstantin Ananyev    &ngx_poll_module_ctx,                  /* module context */
53e18a033bSKonstantin Ananyev    NULL,                                  /* module directives */
54e18a033bSKonstantin Ananyev    NGX_EVENT_MODULE,                      /* module type */
55e18a033bSKonstantin Ananyev    NULL,                                  /* init master */
56e18a033bSKonstantin Ananyev    NULL,                                  /* init module */
57e18a033bSKonstantin Ananyev    NULL,                                  /* init process */
58e18a033bSKonstantin Ananyev    NULL,                                  /* init thread */
59e18a033bSKonstantin Ananyev    NULL,                                  /* exit thread */
60e18a033bSKonstantin Ananyev    NULL,                                  /* exit process */
61e18a033bSKonstantin Ananyev    NULL,                                  /* exit master */
62e18a033bSKonstantin Ananyev    NGX_MODULE_V1_PADDING
63e18a033bSKonstantin Ananyev};
64e18a033bSKonstantin Ananyev
65e18a033bSKonstantin Ananyev
66e18a033bSKonstantin Ananyev
67e18a033bSKonstantin Ananyevstatic ngx_int_t
68e18a033bSKonstantin Ananyevngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
69e18a033bSKonstantin Ananyev{
70e18a033bSKonstantin Ananyev    struct pollfd   *list;
71e18a033bSKonstantin Ananyev
72e18a033bSKonstantin Ananyev    if (event_list == NULL) {
73e18a033bSKonstantin Ananyev        nevents = 0;
74e18a033bSKonstantin Ananyev    }
75e18a033bSKonstantin Ananyev
76e18a033bSKonstantin Ananyev    if (ngx_process >= NGX_PROCESS_WORKER
77e18a033bSKonstantin Ananyev        || cycle->old_cycle == NULL
78e18a033bSKonstantin Ananyev        || cycle->old_cycle->connection_n < cycle->connection_n)
79e18a033bSKonstantin Ananyev    {
80e18a033bSKonstantin Ananyev        list = ngx_alloc(sizeof(struct pollfd) * cycle->connection_n,
81e18a033bSKonstantin Ananyev                         cycle->log);
82e18a033bSKonstantin Ananyev        if (list == NULL) {
83e18a033bSKonstantin Ananyev            return NGX_ERROR;
84e18a033bSKonstantin Ananyev        }
85e18a033bSKonstantin Ananyev
86e18a033bSKonstantin Ananyev        if (event_list) {
87e18a033bSKonstantin Ananyev            ngx_memcpy(list, event_list, sizeof(ngx_event_t *) * nevents);
88e18a033bSKonstantin Ananyev            ngx_free(event_list);
89e18a033bSKonstantin Ananyev        }
90e18a033bSKonstantin Ananyev
91e18a033bSKonstantin Ananyev        event_list = list;
92e18a033bSKonstantin Ananyev    }
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyev    ngx_io = ngx_os_io;
95e18a033bSKonstantin Ananyev
96e18a033bSKonstantin Ananyev    ngx_event_actions = ngx_poll_module_ctx.actions;
97e18a033bSKonstantin Ananyev
98e18a033bSKonstantin Ananyev    ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_FD_EVENT;
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyev    return NGX_OK;
101e18a033bSKonstantin Ananyev}
102e18a033bSKonstantin Ananyev
103e18a033bSKonstantin Ananyev
104e18a033bSKonstantin Ananyevstatic void
105e18a033bSKonstantin Ananyevngx_poll_done(ngx_cycle_t *cycle)
106e18a033bSKonstantin Ananyev{
107e18a033bSKonstantin Ananyev    ngx_free(event_list);
108e18a033bSKonstantin Ananyev
109e18a033bSKonstantin Ananyev    event_list = NULL;
110e18a033bSKonstantin Ananyev}
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyev
113e18a033bSKonstantin Ananyevstatic ngx_int_t
114e18a033bSKonstantin Ananyevngx_poll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
115e18a033bSKonstantin Ananyev{
116e18a033bSKonstantin Ananyev    ngx_event_t       *e;
117e18a033bSKonstantin Ananyev    ngx_connection_t  *c;
118e18a033bSKonstantin Ananyev
119e18a033bSKonstantin Ananyev    c = ev->data;
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyev    ev->active = 1;
122e18a033bSKonstantin Ananyev
123e18a033bSKonstantin Ananyev    if (ev->index != NGX_INVALID_INDEX) {
124e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
125e18a033bSKonstantin Ananyev                      "poll event fd:%d ev:%i is already set", c->fd, event);
126e18a033bSKonstantin Ananyev        return NGX_OK;
127e18a033bSKonstantin Ananyev    }
128e18a033bSKonstantin Ananyev
129e18a033bSKonstantin Ananyev    if (event == NGX_READ_EVENT) {
130e18a033bSKonstantin Ananyev        e = c->write;
131e18a033bSKonstantin Ananyev#if (NGX_READ_EVENT != POLLIN)
132e18a033bSKonstantin Ananyev        event = POLLIN;
133e18a033bSKonstantin Ananyev#endif
134e18a033bSKonstantin Ananyev
135e18a033bSKonstantin Ananyev    } else {
136e18a033bSKonstantin Ananyev        e = c->read;
137e18a033bSKonstantin Ananyev#if (NGX_WRITE_EVENT != POLLOUT)
138e18a033bSKonstantin Ananyev        event = POLLOUT;
139e18a033bSKonstantin Ananyev#endif
140e18a033bSKonstantin Ananyev    }
141e18a033bSKonstantin Ananyev
142e18a033bSKonstantin Ananyev    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
143e18a033bSKonstantin Ananyev                   "poll add event: fd:%d ev:%i", c->fd, event);
144e18a033bSKonstantin Ananyev
145e18a033bSKonstantin Ananyev    if (e == NULL || e->index == NGX_INVALID_INDEX) {
146e18a033bSKonstantin Ananyev        event_list[nevents].fd = c->fd;
147e18a033bSKonstantin Ananyev        event_list[nevents].events = (short) event;
148e18a033bSKonstantin Ananyev        event_list[nevents].revents = 0;
149e18a033bSKonstantin Ananyev
150e18a033bSKonstantin Ananyev        ev->index = nevents;
151e18a033bSKonstantin Ananyev        nevents++;
152e18a033bSKonstantin Ananyev
153e18a033bSKonstantin Ananyev    } else {
154e18a033bSKonstantin Ananyev        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
155e18a033bSKonstantin Ananyev                       "poll add index: %i", e->index);
156e18a033bSKonstantin Ananyev
157e18a033bSKonstantin Ananyev        event_list[e->index].events |= (short) event;
158e18a033bSKonstantin Ananyev        ev->index = e->index;
159e18a033bSKonstantin Ananyev    }
160e18a033bSKonstantin Ananyev
161e18a033bSKonstantin Ananyev    return NGX_OK;
162e18a033bSKonstantin Ananyev}
163e18a033bSKonstantin Ananyev
164e18a033bSKonstantin Ananyev
165e18a033bSKonstantin Ananyevstatic ngx_int_t
166e18a033bSKonstantin Ananyevngx_poll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
167e18a033bSKonstantin Ananyev{
168e18a033bSKonstantin Ananyev    ngx_event_t       *e;
169e18a033bSKonstantin Ananyev    ngx_connection_t  *c;
170e18a033bSKonstantin Ananyev
171e18a033bSKonstantin Ananyev    c = ev->data;
172e18a033bSKonstantin Ananyev
173e18a033bSKonstantin Ananyev    ev->active = 0;
174e18a033bSKonstantin Ananyev
175e18a033bSKonstantin Ananyev    if (ev->index == NGX_INVALID_INDEX) {
176e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
177e18a033bSKonstantin Ananyev                      "poll event fd:%d ev:%i is already deleted",
178e18a033bSKonstantin Ananyev                      c->fd, event);
179e18a033bSKonstantin Ananyev        return NGX_OK;
180e18a033bSKonstantin Ananyev    }
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev    if (event == NGX_READ_EVENT) {
183e18a033bSKonstantin Ananyev        e = c->write;
184e18a033bSKonstantin Ananyev#if (NGX_READ_EVENT != POLLIN)
185e18a033bSKonstantin Ananyev        event = POLLIN;
186e18a033bSKonstantin Ananyev#endif
187e18a033bSKonstantin Ananyev
188e18a033bSKonstantin Ananyev    } else {
189e18a033bSKonstantin Ananyev        e = c->read;
190e18a033bSKonstantin Ananyev#if (NGX_WRITE_EVENT != POLLOUT)
191e18a033bSKonstantin Ananyev        event = POLLOUT;
192e18a033bSKonstantin Ananyev#endif
193e18a033bSKonstantin Ananyev    }
194e18a033bSKonstantin Ananyev
195e18a033bSKonstantin Ananyev    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
196e18a033bSKonstantin Ananyev                   "poll del event: fd:%d ev:%i", c->fd, event);
197e18a033bSKonstantin Ananyev
198e18a033bSKonstantin Ananyev    if (e == NULL || e->index == NGX_INVALID_INDEX) {
199e18a033bSKonstantin Ananyev        nevents--;
200e18a033bSKonstantin Ananyev
201e18a033bSKonstantin Ananyev        if (ev->index < nevents) {
202e18a033bSKonstantin Ananyev
203e18a033bSKonstantin Ananyev            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
204e18a033bSKonstantin Ananyev                           "index: copy event %ui to %i", nevents, ev->index);
205e18a033bSKonstantin Ananyev
206e18a033bSKonstantin Ananyev            event_list[ev->index] = event_list[nevents];
207e18a033bSKonstantin Ananyev
208e18a033bSKonstantin Ananyev            c = ngx_cycle->files[event_list[nevents].fd];
209e18a033bSKonstantin Ananyev
210e18a033bSKonstantin Ananyev            if (c->fd == -1) {
211e18a033bSKonstantin Ananyev                ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
212e18a033bSKonstantin Ananyev                              "unexpected last event");
213e18a033bSKonstantin Ananyev
214e18a033bSKonstantin Ananyev            } else {
215e18a033bSKonstantin Ananyev                if (c->read->index == nevents) {
216e18a033bSKonstantin Ananyev                    c->read->index = ev->index;
217e18a033bSKonstantin Ananyev                }
218e18a033bSKonstantin Ananyev
219e18a033bSKonstantin Ananyev                if (c->write->index == nevents) {
220e18a033bSKonstantin Ananyev                    c->write->index = ev->index;
221e18a033bSKonstantin Ananyev                }
222e18a033bSKonstantin Ananyev            }
223e18a033bSKonstantin Ananyev        }
224e18a033bSKonstantin Ananyev
225e18a033bSKonstantin Ananyev    } else {
226e18a033bSKonstantin Ananyev        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
227e18a033bSKonstantin Ananyev                       "poll del index: %i", e->index);
228e18a033bSKonstantin Ananyev
229e18a033bSKonstantin Ananyev        event_list[e->index].events &= (short) ~event;
230e18a033bSKonstantin Ananyev    }
231e18a033bSKonstantin Ananyev
232e18a033bSKonstantin Ananyev    ev->index = NGX_INVALID_INDEX;
233e18a033bSKonstantin Ananyev
234e18a033bSKonstantin Ananyev    return NGX_OK;
235e18a033bSKonstantin Ananyev}
236e18a033bSKonstantin Ananyev
237e18a033bSKonstantin Ananyev
238e18a033bSKonstantin Ananyevstatic ngx_int_t
239e18a033bSKonstantin Ananyevngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
240e18a033bSKonstantin Ananyev{
241e18a033bSKonstantin Ananyev    int                 ready, revents;
242e18a033bSKonstantin Ananyev    ngx_err_t           err;
243e18a033bSKonstantin Ananyev    ngx_uint_t          i, found, level;
244e18a033bSKonstantin Ananyev    ngx_event_t        *ev;
245e18a033bSKonstantin Ananyev    ngx_queue_t        *queue;
246e18a033bSKonstantin Ananyev    ngx_connection_t   *c;
247e18a033bSKonstantin Ananyev
248e18a033bSKonstantin Ananyev    /* NGX_TIMER_INFINITE == INFTIM */
249e18a033bSKonstantin Ananyev
250e18a033bSKonstantin Ananyev#if (NGX_DEBUG0)
251e18a033bSKonstantin Ananyev    if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
252e18a033bSKonstantin Ananyev        for (i = 0; i < nevents; i++) {
253e18a033bSKonstantin Ananyev            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
254e18a033bSKonstantin Ananyev                           "poll: %ui: fd:%d ev:%04Xd",
255e18a033bSKonstantin Ananyev                           i, event_list[i].fd, event_list[i].events);
256e18a033bSKonstantin Ananyev        }
257e18a033bSKonstantin Ananyev    }
258e18a033bSKonstantin Ananyev#endif
259e18a033bSKonstantin Ananyev
260e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "poll timer: %M", timer);
261e18a033bSKonstantin Ananyev
262e18a033bSKonstantin Ananyev    ready = poll(event_list, (u_int) nevents, (int) timer);
263e18a033bSKonstantin Ananyev
264e18a033bSKonstantin Ananyev    err = (ready == -1) ? ngx_errno : 0;
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyev    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
267e18a033bSKonstantin Ananyev        ngx_time_update();
268e18a033bSKonstantin Ananyev    }
269e18a033bSKonstantin Ananyev
270e18a033bSKonstantin Ananyev    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
271e18a033bSKonstantin Ananyev                   "poll ready %d of %ui", ready, nevents);
272e18a033bSKonstantin Ananyev
273e18a033bSKonstantin Ananyev    if (err) {
274e18a033bSKonstantin Ananyev        if (err == NGX_EINTR) {
275e18a033bSKonstantin Ananyev
276e18a033bSKonstantin Ananyev            if (ngx_event_timer_alarm) {
277e18a033bSKonstantin Ananyev                ngx_event_timer_alarm = 0;
278e18a033bSKonstantin Ananyev                return NGX_OK;
279e18a033bSKonstantin Ananyev            }
280e18a033bSKonstantin Ananyev
281e18a033bSKonstantin Ananyev            level = NGX_LOG_INFO;
282e18a033bSKonstantin Ananyev
283e18a033bSKonstantin Ananyev        } else {
284e18a033bSKonstantin Ananyev            level = NGX_LOG_ALERT;
285e18a033bSKonstantin Ananyev        }
286e18a033bSKonstantin Ananyev
287e18a033bSKonstantin Ananyev        ngx_log_error(level, cycle->log, err, "poll() failed");
288e18a033bSKonstantin Ananyev        return NGX_ERROR;
289e18a033bSKonstantin Ananyev    }
290e18a033bSKonstantin Ananyev
291e18a033bSKonstantin Ananyev    if (ready == 0) {
292e18a033bSKonstantin Ananyev        if (timer != NGX_TIMER_INFINITE) {
293e18a033bSKonstantin Ananyev            return NGX_OK;
294e18a033bSKonstantin Ananyev        }
295e18a033bSKonstantin Ananyev
296e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
297e18a033bSKonstantin Ananyev                      "poll() returned no events without timeout");
298e18a033bSKonstantin Ananyev        return NGX_ERROR;
299e18a033bSKonstantin Ananyev    }
300e18a033bSKonstantin Ananyev
301e18a033bSKonstantin Ananyev    for (i = 0; i < nevents && ready; i++) {
302e18a033bSKonstantin Ananyev
303e18a033bSKonstantin Ananyev        revents = event_list[i].revents;
304e18a033bSKonstantin Ananyev
305e18a033bSKonstantin Ananyev#if 1
306e18a033bSKonstantin Ananyev        ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
307e18a033bSKonstantin Ananyev                       "poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
308e18a033bSKonstantin Ananyev                       i, event_list[i].fd, event_list[i].events, revents);
309e18a033bSKonstantin Ananyev#else
310e18a033bSKonstantin Ananyev        if (revents) {
311e18a033bSKonstantin Ananyev            ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
312e18a033bSKonstantin Ananyev                           "poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
313e18a033bSKonstantin Ananyev                           i, event_list[i].fd, event_list[i].events, revents);
314e18a033bSKonstantin Ananyev        }
315e18a033bSKonstantin Ananyev#endif
316e18a033bSKonstantin Ananyev
317e18a033bSKonstantin Ananyev        if (revents & POLLNVAL) {
318e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
319e18a033bSKonstantin Ananyev                          "poll() error fd:%d ev:%04Xd rev:%04Xd",
320e18a033bSKonstantin Ananyev                          event_list[i].fd, event_list[i].events, revents);
321e18a033bSKonstantin Ananyev        }
322e18a033bSKonstantin Ananyev
323e18a033bSKonstantin Ananyev        if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
324e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
325e18a033bSKonstantin Ananyev                          "strange poll() events fd:%d ev:%04Xd rev:%04Xd",
326e18a033bSKonstantin Ananyev                          event_list[i].fd, event_list[i].events, revents);
327e18a033bSKonstantin Ananyev        }
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyev        if (event_list[i].fd == -1) {
330e18a033bSKonstantin Ananyev            /*
331e18a033bSKonstantin Ananyev             * the disabled event, a workaround for our possible bug,
332e18a033bSKonstantin Ananyev             * see the comment below
333e18a033bSKonstantin Ananyev             */
334e18a033bSKonstantin Ananyev            continue;
335e18a033bSKonstantin Ananyev        }
336e18a033bSKonstantin Ananyev
337e18a033bSKonstantin Ananyev        c = ngx_cycle->files[event_list[i].fd];
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev        if (c->fd == -1) {
340e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");
341e18a033bSKonstantin Ananyev
342e18a033bSKonstantin Ananyev            /*
343e18a033bSKonstantin Ananyev             * it is certainly our fault and it should be investigated,
344e18a033bSKonstantin Ananyev             * in the meantime we disable this event to avoid a CPU spinning
345e18a033bSKonstantin Ananyev             */
346e18a033bSKonstantin Ananyev
347e18a033bSKonstantin Ananyev            if (i == nevents - 1) {
348e18a033bSKonstantin Ananyev                nevents--;
349e18a033bSKonstantin Ananyev            } else {
350e18a033bSKonstantin Ananyev                event_list[i].fd = -1;
351e18a033bSKonstantin Ananyev            }
352e18a033bSKonstantin Ananyev
353e18a033bSKonstantin Ananyev            continue;
354e18a033bSKonstantin Ananyev        }
355e18a033bSKonstantin Ananyev
356e18a033bSKonstantin Ananyev        if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
357e18a033bSKonstantin Ananyev
358e18a033bSKonstantin Ananyev            /*
359e18a033bSKonstantin Ananyev             * if the error events were returned, add POLLIN and POLLOUT
360e18a033bSKonstantin Ananyev             * to handle the events at least in one active handler
361e18a033bSKonstantin Ananyev             */
362e18a033bSKonstantin Ananyev
363e18a033bSKonstantin Ananyev            revents |= POLLIN|POLLOUT;
364e18a033bSKonstantin Ananyev        }
365e18a033bSKonstantin Ananyev
366e18a033bSKonstantin Ananyev        found = 0;
367e18a033bSKonstantin Ananyev
368e18a033bSKonstantin Ananyev        if ((revents & POLLIN) && c->read->active) {
369e18a033bSKonstantin Ananyev            found = 1;
370e18a033bSKonstantin Ananyev
371e18a033bSKonstantin Ananyev            ev = c->read;
372e18a033bSKonstantin Ananyev            ev->ready = 1;
373e18a033bSKonstantin Ananyev
374e18a033bSKonstantin Ananyev            queue = ev->accept ? &ngx_posted_accept_events
375e18a033bSKonstantin Ananyev                               : &ngx_posted_events;
376e18a033bSKonstantin Ananyev
377e18a033bSKonstantin Ananyev            ngx_post_event(ev, queue);
378e18a033bSKonstantin Ananyev        }
379e18a033bSKonstantin Ananyev
380e18a033bSKonstantin Ananyev        if ((revents & POLLOUT) && c->write->active) {
381e18a033bSKonstantin Ananyev            found = 1;
382e18a033bSKonstantin Ananyev
383e18a033bSKonstantin Ananyev            ev = c->write;
384e18a033bSKonstantin Ananyev            ev->ready = 1;
385e18a033bSKonstantin Ananyev
386e18a033bSKonstantin Ananyev            ngx_post_event(ev, &ngx_posted_events);
387e18a033bSKonstantin Ananyev        }
388e18a033bSKonstantin Ananyev
389e18a033bSKonstantin Ananyev        if (found) {
390e18a033bSKonstantin Ananyev            ready--;
391e18a033bSKonstantin Ananyev            continue;
392e18a033bSKonstantin Ananyev        }
393e18a033bSKonstantin Ananyev    }
394e18a033bSKonstantin Ananyev
395e18a033bSKonstantin Ananyev    if (ready != 0) {
396e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "poll ready != events");
397e18a033bSKonstantin Ananyev    }
398e18a033bSKonstantin Ananyev
399e18a033bSKonstantin Ananyev    return NGX_OK;
400e18a033bSKonstantin Ananyev}
401e18a033bSKonstantin Ananyev
402e18a033bSKonstantin Ananyev
403e18a033bSKonstantin Ananyevstatic char *
404e18a033bSKonstantin Ananyevngx_poll_init_conf(ngx_cycle_t *cycle, void *conf)
405e18a033bSKonstantin Ananyev{
406e18a033bSKonstantin Ananyev    ngx_event_conf_t  *ecf;
407e18a033bSKonstantin Ananyev
408e18a033bSKonstantin Ananyev    ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
409e18a033bSKonstantin Ananyev
410e18a033bSKonstantin Ananyev    if (ecf->use != ngx_poll_module.ctx_index) {
411e18a033bSKonstantin Ananyev        return NGX_CONF_OK;
412e18a033bSKonstantin Ananyev    }
413e18a033bSKonstantin Ananyev
414e18a033bSKonstantin Ananyev    return NGX_CONF_OK;
415e18a033bSKonstantin Ananyev}
416