comparison src/event/modules/ngx_win32_select_module.c @ 488:829f9a66a659 NGINX_0_7_56

nginx 0.7.56 *) Feature: nginx/Windows supports IPv6 in a "listen" directive of the HTTP module. *) Bugfix: in ngx_http_image_filter_module.
author Igor Sysoev <http://sysoev.ru>
date Mon, 11 May 2009 00:00:00 +0400
parents
children 86dad910eeb6
comparison
equal deleted inserted replaced
487:e98b980b4fe7 488:829f9a66a659
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 if (ready == -1) {
270 err = ngx_socket_errno;
271 } else {
272 err = 0;
273 }
274
275 if (flags & NGX_UPDATE_TIME) {
276 ngx_time_update(0, 0);
277 }
278
279 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
280 "select ready %d", ready);
281
282 if (err) {
283 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");
284
285 if (err == WSAENOTSOCK) {
286 ngx_select_repair_fd_sets(cycle);
287 }
288
289 return NGX_ERROR;
290 }
291
292 if (ready == 0) {
293 if (timer != NGX_TIMER_INFINITE) {
294 return NGX_OK;
295 }
296
297 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
298 "select() returned no events without timeout");
299 return NGX_ERROR;
300 }
301
302 ngx_mutex_lock(ngx_posted_events_mutex);
303
304 nready = 0;
305
306 for (i = 0; i < nevents; i++) {
307 ev = event_index[i];
308 c = ev->data;
309 found = 0;
310
311 if (ev->write) {
312 if (FD_ISSET(c->fd, &work_write_fd_set)) {
313 found = 1;
314 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
315 "select write %d", c->fd);
316 }
317
318 } else {
319 if (FD_ISSET(c->fd, &work_read_fd_set)) {
320 found = 1;
321 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
322 "select read %d", c->fd);
323 }
324 }
325
326 if (found) {
327 ev->ready = 1;
328
329 queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
330 &ngx_posted_events);
331 ngx_locked_post_event(ev, queue);
332
333 nready++;
334 }
335 }
336
337 ngx_mutex_unlock(ngx_posted_events_mutex);
338
339 if (ready != nready) {
340 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
341 "select ready != events: %d:%d", ready, nready);
342
343 ngx_select_repair_fd_sets(cycle);
344 }
345
346 return NGX_OK;
347 }
348
349
350 static void
351 ngx_select_repair_fd_sets(ngx_cycle_t *cycle)
352 {
353 int n;
354 u_int i;
355 socklen_t len;
356 ngx_err_t err;
357 ngx_socket_t s;
358
359 for (i = 0; i < master_read_fd_set.fd_count; i++) {
360
361 s = master_read_fd_set.fd_array[i];
362 len = sizeof(int);
363
364 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
365 err = ngx_socket_errno;
366
367 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
368 "invalid descriptor #%d in read fd_set", s);
369
370 FD_CLR(s, &master_read_fd_set);
371 }
372 }
373
374 for (i = 0; i < master_write_fd_set.fd_count; i++) {
375
376 s = master_write_fd_set.fd_array[i];
377 len = sizeof(int);
378
379 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
380 err = ngx_socket_errno;
381
382 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
383 "invalid descriptor #%d in write fd_set", s);
384
385 FD_CLR(s, &master_write_fd_set);
386 }
387 }
388 }
389
390
391 static char *
392 ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
393 {
394 ngx_event_conf_t *ecf;
395
396 ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
397
398 if (ecf->use != ngx_select_module.ctx_index) {
399 return NGX_CONF_OK;
400 }
401
402 return NGX_CONF_OK;
403 }