~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/event/modules/ngx_win32_select_module.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.