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_select_init(ngx_cycle_t *cycle, ngx_msec_t timer);
14e18a033bSKonstantin Ananyevstatic void ngx_select_done(ngx_cycle_t *cycle);
15e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_select_add_event(ngx_event_t *ev, ngx_int_t event,
16e18a033bSKonstantin Ananyev    ngx_uint_t flags);
17e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_select_del_event(ngx_event_t *ev, ngx_int_t event,
18e18a033bSKonstantin Ananyev    ngx_uint_t flags);
19e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
20e18a033bSKonstantin Ananyev    ngx_uint_t flags);
21e18a033bSKonstantin Ananyevstatic void ngx_select_repair_fd_sets(ngx_cycle_t *cycle);
22e18a033bSKonstantin Ananyevstatic char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);
23e18a033bSKonstantin Ananyev
24e18a033bSKonstantin Ananyev
25e18a033bSKonstantin Ananyevstatic fd_set         master_read_fd_set;
26e18a033bSKonstantin Ananyevstatic fd_set         master_write_fd_set;
27e18a033bSKonstantin Ananyevstatic fd_set         work_read_fd_set;
28e18a033bSKonstantin Ananyevstatic fd_set         work_write_fd_set;
29e18a033bSKonstantin Ananyev
30e18a033bSKonstantin Ananyevstatic ngx_int_t      max_fd;
31e18a033bSKonstantin Ananyevstatic ngx_uint_t     nevents;
32e18a033bSKonstantin Ananyev
33e18a033bSKonstantin Ananyevstatic ngx_event_t  **event_index;
34e18a033bSKonstantin Ananyev
35e18a033bSKonstantin Ananyev
36e18a033bSKonstantin Ananyevstatic ngx_str_t           select_name = ngx_string("select");
37e18a033bSKonstantin Ananyev
38e18a033bSKonstantin Ananyevstatic ngx_event_module_t  ngx_select_module_ctx = {
39e18a033bSKonstantin Ananyev    &select_name,
40e18a033bSKonstantin Ananyev    NULL,                                  /* create configuration */
41e18a033bSKonstantin Ananyev    ngx_select_init_conf,                  /* init configuration */
42e18a033bSKonstantin Ananyev
43e18a033bSKonstantin Ananyev    {
44e18a033bSKonstantin Ananyev        ngx_select_add_event,              /* add an event */
45e18a033bSKonstantin Ananyev        ngx_select_del_event,              /* delete an event */
46e18a033bSKonstantin Ananyev        ngx_select_add_event,              /* enable an event */
47e18a033bSKonstantin Ananyev        ngx_select_del_event,              /* disable an event */
48e18a033bSKonstantin Ananyev        NULL,                              /* add an connection */
49e18a033bSKonstantin Ananyev        NULL,                              /* delete an connection */
50e18a033bSKonstantin Ananyev        NULL,                              /* trigger a notify */
51e18a033bSKonstantin Ananyev        ngx_select_process_events,         /* process the events */
52e18a033bSKonstantin Ananyev        ngx_select_init,                   /* init the events */
53e18a033bSKonstantin Ananyev        ngx_select_done                    /* done the events */
54e18a033bSKonstantin Ananyev    }
55e18a033bSKonstantin Ananyev
56e18a033bSKonstantin Ananyev};
57e18a033bSKonstantin Ananyev
58e18a033bSKonstantin Ananyevngx_module_t  ngx_select_module = {
59e18a033bSKonstantin Ananyev    NGX_MODULE_V1,
60e18a033bSKonstantin Ananyev    &ngx_select_module_ctx,                /* module context */
61e18a033bSKonstantin Ananyev    NULL,                                  /* module directives */
62e18a033bSKonstantin Ananyev    NGX_EVENT_MODULE,                      /* module type */
63e18a033bSKonstantin Ananyev    NULL,                                  /* init master */
64e18a033bSKonstantin Ananyev    NULL,                                  /* init module */
65e18a033bSKonstantin Ananyev    NULL,                                  /* init process */
66e18a033bSKonstantin Ananyev    NULL,                                  /* init thread */
67e18a033bSKonstantin Ananyev    NULL,                                  /* exit thread */
68e18a033bSKonstantin Ananyev    NULL,                                  /* exit process */
69e18a033bSKonstantin Ananyev    NULL,                                  /* exit master */
70e18a033bSKonstantin Ananyev    NGX_MODULE_V1_PADDING
71e18a033bSKonstantin Ananyev};
72e18a033bSKonstantin Ananyev
73e18a033bSKonstantin Ananyev
74e18a033bSKonstantin Ananyevstatic ngx_int_t
75e18a033bSKonstantin Ananyevngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer)
76e18a033bSKonstantin Ananyev{
77e18a033bSKonstantin Ananyev    ngx_event_t  **index;
78e18a033bSKonstantin Ananyev
79e18a033bSKonstantin Ananyev    if (event_index == NULL) {
80e18a033bSKonstantin Ananyev        FD_ZERO(&master_read_fd_set);
81e18a033bSKonstantin Ananyev        FD_ZERO(&master_write_fd_set);
82e18a033bSKonstantin Ananyev        nevents = 0;
83e18a033bSKonstantin Ananyev    }
84e18a033bSKonstantin Ananyev
85e18a033bSKonstantin Ananyev    if (ngx_process >= NGX_PROCESS_WORKER
86e18a033bSKonstantin Ananyev        || cycle->old_cycle == NULL
87e18a033bSKonstantin Ananyev        || cycle->old_cycle->connection_n < cycle->connection_n)
88e18a033bSKonstantin Ananyev    {
89e18a033bSKonstantin Ananyev        index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
90e18a033bSKonstantin Ananyev                          cycle->log);
91e18a033bSKonstantin Ananyev        if (index == NULL) {
92e18a033bSKonstantin Ananyev            return NGX_ERROR;
93e18a033bSKonstantin Ananyev        }
94e18a033bSKonstantin Ananyev
95e18a033bSKonstantin Ananyev        if (event_index) {
96e18a033bSKonstantin Ananyev            ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents);
97e18a033bSKonstantin Ananyev            ngx_free(event_index);
98e18a033bSKonstantin Ananyev        }
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyev        event_index = index;
101e18a033bSKonstantin Ananyev    }
102e18a033bSKonstantin Ananyev
103e18a033bSKonstantin Ananyev    ngx_io = ngx_os_io;
104e18a033bSKonstantin Ananyev
105e18a033bSKonstantin Ananyev    ngx_event_actions = ngx_select_module_ctx.actions;
106e18a033bSKonstantin Ananyev
107e18a033bSKonstantin Ananyev    ngx_event_flags = NGX_USE_LEVEL_EVENT;
108e18a033bSKonstantin Ananyev
109e18a033bSKonstantin Ananyev    max_fd = -1;
110e18a033bSKonstantin Ananyev
111e18a033bSKonstantin Ananyev    return NGX_OK;
112e18a033bSKonstantin Ananyev}
113e18a033bSKonstantin Ananyev
114e18a033bSKonstantin Ananyev
115e18a033bSKonstantin Ananyevstatic void
116e18a033bSKonstantin Ananyevngx_select_done(ngx_cycle_t *cycle)
117e18a033bSKonstantin Ananyev{
118e18a033bSKonstantin Ananyev    ngx_free(event_index);
119e18a033bSKonstantin Ananyev
120e18a033bSKonstantin Ananyev    event_index = NULL;
121e18a033bSKonstantin Ananyev}
122e18a033bSKonstantin Ananyev
123e18a033bSKonstantin Ananyev
124e18a033bSKonstantin Ananyevstatic ngx_int_t
125e18a033bSKonstantin Ananyevngx_select_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
126e18a033bSKonstantin Ananyev{
127e18a033bSKonstantin Ananyev    ngx_connection_t  *c;
128e18a033bSKonstantin Ananyev
129e18a033bSKonstantin Ananyev    c = ev->data;
130e18a033bSKonstantin Ananyev
131e18a033bSKonstantin Ananyev    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
132e18a033bSKonstantin Ananyev                   "select add event fd:%d ev:%i", c->fd, event);
133e18a033bSKonstantin Ananyev
134e18a033bSKonstantin Ananyev    if (ev->index != NGX_INVALID_INDEX) {
135e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
136e18a033bSKonstantin Ananyev                      "select event fd:%d ev:%i is already set", c->fd, event);
137e18a033bSKonstantin Ananyev        return NGX_OK;
138e18a033bSKonstantin Ananyev    }
139e18a033bSKonstantin Ananyev
140e18a033bSKonstantin Ananyev    if ((event == NGX_READ_EVENT && ev->write)
141e18a033bSKonstantin Ananyev        || (event == NGX_WRITE_EVENT && !ev->write))
142e18a033bSKonstantin Ananyev    {
143e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
144e18a033bSKonstantin Ananyev                      "invalid select %s event fd:%d ev:%i",
145e18a033bSKonstantin Ananyev                      ev->write ? "write" : "read", c->fd, event);
146e18a033bSKonstantin Ananyev        return NGX_ERROR;
147e18a033bSKonstantin Ananyev    }
148e18a033bSKonstantin Ananyev
149e18a033bSKonstantin Ananyev    if (event == NGX_READ_EVENT) {
150e18a033bSKonstantin Ananyev        FD_SET(c->fd, &master_read_fd_set);
151e18a033bSKonstantin Ananyev
152e18a033bSKonstantin Ananyev    } else if (event == NGX_WRITE_EVENT) {
153e18a033bSKonstantin Ananyev        FD_SET(c->fd, &master_write_fd_set);
154e18a033bSKonstantin Ananyev    }
155e18a033bSKonstantin Ananyev
156e18a033bSKonstantin Ananyev    if (max_fd != -1 && max_fd < c->fd) {
157e18a033bSKonstantin Ananyev        max_fd = c->fd;
158e18a033bSKonstantin Ananyev    }
159e18a033bSKonstantin Ananyev
160e18a033bSKonstantin Ananyev    ev->active = 1;
161e18a033bSKonstantin Ananyev
162e18a033bSKonstantin Ananyev    event_index[nevents] = ev;
163e18a033bSKonstantin Ananyev    ev->index = nevents;
164e18a033bSKonstantin Ananyev    nevents++;
165e18a033bSKonstantin Ananyev
166e18a033bSKonstantin Ananyev    return NGX_OK;
167e18a033bSKonstantin Ananyev}
168e18a033bSKonstantin Ananyev
169e18a033bSKonstantin Ananyev
170e18a033bSKonstantin Ananyevstatic ngx_int_t
171e18a033bSKonstantin Ananyevngx_select_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
172e18a033bSKonstantin Ananyev{
173e18a033bSKonstantin Ananyev    ngx_event_t       *e;
174e18a033bSKonstantin Ananyev    ngx_connection_t  *c;
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev    c = ev->data;
177e18a033bSKonstantin Ananyev
178e18a033bSKonstantin Ananyev    ev->active = 0;
179e18a033bSKonstantin Ananyev
180e18a033bSKonstantin Ananyev    if (ev->index == NGX_INVALID_INDEX) {
181e18a033bSKonstantin Ananyev        return NGX_OK;
182e18a033bSKonstantin Ananyev    }
183e18a033bSKonstantin Ananyev
184e18a033bSKonstantin Ananyev    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
185e18a033bSKonstantin Ananyev                   "select del event fd:%d ev:%i", c->fd, event);
186e18a033bSKonstantin Ananyev
187e18a033bSKonstantin Ananyev    if (event == NGX_READ_EVENT) {
188e18a033bSKonstantin Ananyev        FD_CLR(c->fd, &master_read_fd_set);
189e18a033bSKonstantin Ananyev
190e18a033bSKonstantin Ananyev    } else if (event == NGX_WRITE_EVENT) {
191e18a033bSKonstantin Ananyev        FD_CLR(c->fd, &master_write_fd_set);
192e18a033bSKonstantin Ananyev    }
193e18a033bSKonstantin Ananyev
194e18a033bSKonstantin Ananyev    if (max_fd == c->fd) {
195e18a033bSKonstantin Ananyev        max_fd = -1;
196e18a033bSKonstantin Ananyev    }
197e18a033bSKonstantin Ananyev
198e18a033bSKonstantin Ananyev    if (ev->index < --nevents) {
199e18a033bSKonstantin Ananyev        e = event_index[nevents];
200e18a033bSKonstantin Ananyev        event_index[ev->index] = e;
201e18a033bSKonstantin Ananyev        e->index = ev->index;
202e18a033bSKonstantin Ananyev    }
203e18a033bSKonstantin Ananyev
204e18a033bSKonstantin Ananyev    ev->index = NGX_INVALID_INDEX;
205e18a033bSKonstantin Ananyev
206e18a033bSKonstantin Ananyev    return NGX_OK;
207e18a033bSKonstantin Ananyev}
208e18a033bSKonstantin Ananyev
209e18a033bSKonstantin Ananyev
210e18a033bSKonstantin Ananyevstatic ngx_int_t
211e18a033bSKonstantin Ananyevngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
212e18a033bSKonstantin Ananyev    ngx_uint_t flags)
213e18a033bSKonstantin Ananyev{
214e18a033bSKonstantin Ananyev    int                ready, nready;
215e18a033bSKonstantin Ananyev    ngx_err_t          err;
216e18a033bSKonstantin Ananyev    ngx_uint_t         i, found;
217e18a033bSKonstantin Ananyev    ngx_event_t       *ev;
218e18a033bSKonstantin Ananyev    ngx_queue_t       *queue;
219e18a033bSKonstantin Ananyev    struct timeval     tv, *tp;
220e18a033bSKonstantin Ananyev    ngx_connection_t  *c;
221e18a033bSKonstantin Ananyev
222e18a033bSKonstantin Ananyev    if (max_fd == -1) {
223e18a033bSKonstantin Ananyev        for (i = 0; i < nevents; i++) {
224e18a033bSKonstantin Ananyev            c = event_index[i]->data;
225e18a033bSKonstantin Ananyev            if (max_fd < c->fd) {
226e18a033bSKonstantin Ananyev                max_fd = c->fd;
227e18a033bSKonstantin Ananyev            }
228e18a033bSKonstantin Ananyev        }
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
231e18a033bSKonstantin Ananyev                       "change max_fd: %i", max_fd);
232e18a033bSKonstantin Ananyev    }
233e18a033bSKonstantin Ananyev
234e18a033bSKonstantin Ananyev#if (NGX_DEBUG)
235e18a033bSKonstantin Ananyev    if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
236e18a033bSKonstantin Ananyev        for (i = 0; i < nevents; i++) {
237e18a033bSKonstantin Ananyev            ev = event_index[i];
238e18a033bSKonstantin Ananyev            c = ev->data;
239e18a033bSKonstantin Ananyev            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
240e18a033bSKonstantin Ananyev                           "select event: fd:%d wr:%d", c->fd, ev->write);
241e18a033bSKonstantin Ananyev        }
242e18a033bSKonstantin Ananyev
243e18a033bSKonstantin Ananyev        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
244e18a033bSKonstantin Ananyev                       "max_fd: %i", max_fd);
245e18a033bSKonstantin Ananyev    }
246e18a033bSKonstantin Ananyev#endif
247e18a033bSKonstantin Ananyev
248e18a033bSKonstantin Ananyev    if (timer == NGX_TIMER_INFINITE) {
249e18a033bSKonstantin Ananyev        tp = NULL;
250e18a033bSKonstantin Ananyev
251e18a033bSKonstantin Ananyev    } else {
252e18a033bSKonstantin Ananyev        tv.tv_sec = (long) (timer / 1000);
253e18a033bSKonstantin Ananyev        tv.tv_usec = (long) ((timer % 1000) * 1000);
254e18a033bSKonstantin Ananyev        tp = &tv;
255e18a033bSKonstantin Ananyev    }
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
258e18a033bSKonstantin Ananyev                   "select timer: %M", timer);
259e18a033bSKonstantin Ananyev
260e18a033bSKonstantin Ananyev    work_read_fd_set = master_read_fd_set;
261e18a033bSKonstantin Ananyev    work_write_fd_set = master_write_fd_set;
262e18a033bSKonstantin Ananyev
263e18a033bSKonstantin Ananyev    ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp);
264e18a033bSKonstantin Ananyev
265e18a033bSKonstantin Ananyev    err = (ready == -1) ? ngx_errno : 0;
266e18a033bSKonstantin Ananyev
267e18a033bSKonstantin Ananyev    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
268e18a033bSKonstantin Ananyev        ngx_time_update();
269e18a033bSKonstantin Ananyev    }
270e18a033bSKonstantin Ananyev
271e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
272e18a033bSKonstantin Ananyev                   "select ready %d", ready);
273e18a033bSKonstantin Ananyev
274e18a033bSKonstantin Ananyev    if (err) {
275e18a033bSKonstantin Ananyev        ngx_uint_t  level;
276e18a033bSKonstantin Ananyev
277e18a033bSKonstantin Ananyev        if (err == NGX_EINTR) {
278e18a033bSKonstantin Ananyev
279e18a033bSKonstantin Ananyev            if (ngx_event_timer_alarm) {
280e18a033bSKonstantin Ananyev                ngx_event_timer_alarm = 0;
281e18a033bSKonstantin Ananyev                return NGX_OK;
282e18a033bSKonstantin Ananyev            }
283e18a033bSKonstantin Ananyev
284e18a033bSKonstantin Ananyev            level = NGX_LOG_INFO;
285e18a033bSKonstantin Ananyev
286e18a033bSKonstantin Ananyev        } else {
287e18a033bSKonstantin Ananyev            level = NGX_LOG_ALERT;
288e18a033bSKonstantin Ananyev        }
289e18a033bSKonstantin Ananyev
290e18a033bSKonstantin Ananyev        ngx_log_error(level, cycle->log, err, "select() failed");
291e18a033bSKonstantin Ananyev
292e18a033bSKonstantin Ananyev        if (err == NGX_EBADF) {
293e18a033bSKonstantin Ananyev            ngx_select_repair_fd_sets(cycle);
294e18a033bSKonstantin Ananyev        }
295e18a033bSKonstantin Ananyev
296e18a033bSKonstantin Ananyev        return NGX_ERROR;
297e18a033bSKonstantin Ananyev    }
298e18a033bSKonstantin Ananyev
299e18a033bSKonstantin Ananyev    if (ready == 0) {
300e18a033bSKonstantin Ananyev        if (timer != NGX_TIMER_INFINITE) {
301e18a033bSKonstantin Ananyev            return NGX_OK;
302e18a033bSKonstantin Ananyev        }
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
305e18a033bSKonstantin Ananyev                      "select() returned no events without timeout");
306e18a033bSKonstantin Ananyev        return NGX_ERROR;
307e18a033bSKonstantin Ananyev    }
308e18a033bSKonstantin Ananyev
309e18a033bSKonstantin Ananyev    nready = 0;
310e18a033bSKonstantin Ananyev
311e18a033bSKonstantin Ananyev    for (i = 0; i < nevents; i++) {
312e18a033bSKonstantin Ananyev        ev = event_index[i];
313e18a033bSKonstantin Ananyev        c = ev->data;
314e18a033bSKonstantin Ananyev        found = 0;
315e18a033bSKonstantin Ananyev
316e18a033bSKonstantin Ananyev        if (ev->write) {
317e18a033bSKonstantin Ananyev            if (FD_ISSET(c->fd, &work_write_fd_set)) {
318e18a033bSKonstantin Ananyev                found = 1;
319e18a033bSKonstantin Ananyev                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
320e18a033bSKonstantin Ananyev                               "select write %d", c->fd);
321e18a033bSKonstantin Ananyev            }
322e18a033bSKonstantin Ananyev
323e18a033bSKonstantin Ananyev        } else {
324e18a033bSKonstantin Ananyev            if (FD_ISSET(c->fd, &work_read_fd_set)) {
325e18a033bSKonstantin Ananyev                found = 1;
326e18a033bSKonstantin Ananyev                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
327e18a033bSKonstantin Ananyev                               "select read %d", c->fd);
328e18a033bSKonstantin Ananyev            }
329e18a033bSKonstantin Ananyev        }
330e18a033bSKonstantin Ananyev
331e18a033bSKonstantin Ananyev        if (found) {
332e18a033bSKonstantin Ananyev            ev->ready = 1;
333e18a033bSKonstantin Ananyev
334e18a033bSKonstantin Ananyev            queue = ev->accept ? &ngx_posted_accept_events
335e18a033bSKonstantin Ananyev                               : &ngx_posted_events;
336e18a033bSKonstantin Ananyev
337e18a033bSKonstantin Ananyev            ngx_post_event(ev, queue);
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev            nready++;
340e18a033bSKonstantin Ananyev        }
341e18a033bSKonstantin Ananyev    }
342e18a033bSKonstantin Ananyev
343e18a033bSKonstantin Ananyev    if (ready != nready) {
344e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
345e18a033bSKonstantin Ananyev                      "select ready != events: %d:%d", ready, nready);
346e18a033bSKonstantin Ananyev
347e18a033bSKonstantin Ananyev        ngx_select_repair_fd_sets(cycle);
348e18a033bSKonstantin Ananyev    }
349e18a033bSKonstantin Ananyev
350e18a033bSKonstantin Ananyev    return NGX_OK;
351e18a033bSKonstantin Ananyev}
352e18a033bSKonstantin Ananyev
353e18a033bSKonstantin Ananyev
354e18a033bSKonstantin Ananyevstatic void
355e18a033bSKonstantin Ananyevngx_select_repair_fd_sets(ngx_cycle_t *cycle)
356e18a033bSKonstantin Ananyev{
357e18a033bSKonstantin Ananyev    int           n;
358e18a033bSKonstantin Ananyev    socklen_t     len;
359e18a033bSKonstantin Ananyev    ngx_err_t     err;
360e18a033bSKonstantin Ananyev    ngx_socket_t  s;
361e18a033bSKonstantin Ananyev
362e18a033bSKonstantin Ananyev    for (s = 0; s <= max_fd; s++) {
363e18a033bSKonstantin Ananyev
364e18a033bSKonstantin Ananyev        if (FD_ISSET(s, &master_read_fd_set) == 0) {
365e18a033bSKonstantin Ananyev            continue;
366e18a033bSKonstantin Ananyev        }
367e18a033bSKonstantin Ananyev
368e18a033bSKonstantin Ananyev        len = sizeof(int);
369e18a033bSKonstantin Ananyev
370e18a033bSKonstantin Ananyev        if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) {
371e18a033bSKonstantin Ananyev            err = ngx_socket_errno;
372e18a033bSKonstantin Ananyev
373e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
374e18a033bSKonstantin Ananyev                          "invalid descriptor #%d in read fd_set", s);
375e18a033bSKonstantin Ananyev
376e18a033bSKonstantin Ananyev            FD_CLR(s, &master_read_fd_set);
377e18a033bSKonstantin Ananyev        }
378e18a033bSKonstantin Ananyev    }
379e18a033bSKonstantin Ananyev
380e18a033bSKonstantin Ananyev    for (s = 0; s <= max_fd; s++) {
381e18a033bSKonstantin Ananyev
382e18a033bSKonstantin Ananyev        if (FD_ISSET(s, &master_write_fd_set) == 0) {
383e18a033bSKonstantin Ananyev            continue;
384e18a033bSKonstantin Ananyev        }
385e18a033bSKonstantin Ananyev
386e18a033bSKonstantin Ananyev        len = sizeof(int);
387e18a033bSKonstantin Ananyev
388e18a033bSKonstantin Ananyev        if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) {
389e18a033bSKonstantin Ananyev            err = ngx_socket_errno;
390e18a033bSKonstantin Ananyev
391e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
392e18a033bSKonstantin Ananyev                          "invalid descriptor #%d in write fd_set", s);
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyev            FD_CLR(s, &master_write_fd_set);
395e18a033bSKonstantin Ananyev        }
396e18a033bSKonstantin Ananyev    }
397e18a033bSKonstantin Ananyev
398e18a033bSKonstantin Ananyev    max_fd = -1;
399e18a033bSKonstantin Ananyev}
400e18a033bSKonstantin Ananyev
401e18a033bSKonstantin Ananyev
402e18a033bSKonstantin Ananyevstatic char *
403e18a033bSKonstantin Ananyevngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
404e18a033bSKonstantin Ananyev{
405e18a033bSKonstantin Ananyev    ngx_event_conf_t  *ecf;
406e18a033bSKonstantin Ananyev
407e18a033bSKonstantin Ananyev    ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
408e18a033bSKonstantin Ananyev
409e18a033bSKonstantin Ananyev    if (ecf->use != ngx_select_module.ctx_index) {
410e18a033bSKonstantin Ananyev        return NGX_CONF_OK;
411e18a033bSKonstantin Ananyev    }
412e18a033bSKonstantin Ananyev
413e18a033bSKonstantin Ananyev    /* disable warning: the default FD_SETSIZE is 1024U in FreeBSD 5.x */
414e18a033bSKonstantin Ananyev
415e18a033bSKonstantin Ananyev    if (cycle->connection_n > FD_SETSIZE) {
416e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
417e18a033bSKonstantin Ananyev                      "the maximum number of files "
418e18a033bSKonstantin Ananyev                      "supported by select() is %ud", FD_SETSIZE);
419e18a033bS