Klaus Demo nginx / 6ce6fcd
divide select module into two modules: Unix and Win32 ones Igor Sysoev 10 years ago
4 changed file(s) with 420 addition(s) and 151 deletion(s). Raw diff Collapse all Expand all
99 OS_CONFIG="$WIN32_CONFIG"
1010 CORE_LIBS="$CORE_LIBS advapi32.lib ws2_32.lib"
1111 NGX_ICONS="$NGX_WIN32_ICONS"
12 SELECT_SRCS=$WIN32_SELECT_SRCS
1213
1314 EVENT_MODULES="$EVENT_MODULES $IOCP_MODULE"
1415 EVENT_FOUND=YES
9494
9595 SELECT_MODULE=ngx_select_module
9696 SELECT_SRCS=src/event/modules/ngx_select_module.c
97 WIN32_SELECT_SRCS=src/event/modules/ngx_win32_select_module.c
9798
9899 POLL_MODULE=ngx_poll_module
99100 POLL_SRCS=src/event/modules/ngx_poll_module.c
66 #include <ngx_config.h>
77 #include <ngx_core.h>
88 #include <ngx_event.h>
9
109
1110
1211 static ngx_int_t ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer);
2625 static fd_set work_read_fd_set;
2726 static fd_set work_write_fd_set;
2827
29 #if (NGX_WIN32)
30 static ngx_uint_t max_read;
31 static ngx_uint_t max_write;
32 #else
3328 static ngx_int_t max_fd;
34 #endif
35
3629 static ngx_uint_t nevents;
3730
3831 static ngx_event_t **event_index;
111104
112105 ngx_event_flags = NGX_USE_LEVEL_EVENT;
113106
114 #if (NGX_WIN32)
115 max_read = max_write = 0;
116 #else
117107 max_fd = -1;
118 #endif
119108
120109 return NGX_OK;
121110 }
155144 return NGX_ERROR;
156145 }
157146
158
159 #if (NGX_WIN32)
160
161 if ((event == NGX_READ_EVENT) && (max_read >= FD_SETSIZE)
162 || (event == NGX_WRITE_EVENT) && (max_write >= FD_SETSIZE))
163 {
164 ngx_log_error(NGX_LOG_ERR, ev->log, 0,
165 "maximum number of descriptors "
166 "supported by select() is %d", FD_SETSIZE);
167 return NGX_ERROR;
168 }
169
170147 if (event == NGX_READ_EVENT) {
171148 FD_SET(c->fd, &master_read_fd_set);
172 max_read++;
173149
174150 } else if (event == NGX_WRITE_EVENT) {
175151 FD_SET(c->fd, &master_write_fd_set);
176 max_write++;
177 }
178
179 #else
180
181 if (event == NGX_READ_EVENT) {
182 FD_SET(c->fd, &master_read_fd_set);
183
184 } else if (event == NGX_WRITE_EVENT) {
185 FD_SET(c->fd, &master_write_fd_set);
186152 }
187153
188154 if (max_fd != -1 && max_fd < c->fd) {
189155 max_fd = c->fd;
190156 }
191
192 #endif
193157
194158 ev->active = 1;
195159
218182 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
219183 "select del event fd:%d ev:%i", c->fd, event);
220184
221 #if (NGX_WIN32)
222
223185 if (event == NGX_READ_EVENT) {
224186 FD_CLR(c->fd, &master_read_fd_set);
225 max_read--;
226187
227188 } else if (event == NGX_WRITE_EVENT) {
228189 FD_CLR(c->fd, &master_write_fd_set);
229 max_write--;
230 }
231
232 #else
233
234 if (event == NGX_READ_EVENT) {
235 FD_CLR(c->fd, &master_read_fd_set);
236
237 } else if (event == NGX_WRITE_EVENT) {
238 FD_CLR(c->fd, &master_write_fd_set);
239190 }
240191
241192 if (max_fd == c->fd) {
242193 max_fd = -1;
243194 }
244
245 #endif
246195
247196 if (ev->index < --nevents) {
248197 e = event_index[nevents];
267216 struct timeval tv, *tp;
268217 ngx_connection_t *c;
269218
270 #if !(NGX_WIN32)
271
272219 if (max_fd == -1) {
273220 for (i = 0; i < nevents; i++) {
274221 c = event_index[i]->data;
280227 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
281228 "change max_fd: %d", max_fd);
282229 }
283
284 #endif
285230
286231 #if (NGX_DEBUG)
287232 if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
292237 "select event: fd:%d wr:%d", c->fd, ev->write);
293238 }
294239
295 #if !(NGX_WIN32)
296240 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
297241 "max_fd: %d", max_fd);
298 #endif
299242 }
300243 #endif
301244
314257 work_read_fd_set = master_read_fd_set;
315258 work_write_fd_set = master_write_fd_set;
316259
317 #if (NGX_WIN32)
318
319 if (max_read || max_write) {
320 ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);
321
322 } else {
323
324 /*
325 * Winsock select() requires that at least one descriptor set must be
326 * be non-null, and any non-null descriptor set must contain at least
327 * one handle to a socket. Otherwise select() returns WSAEINVAL.
328 */
329
330 ngx_msleep(timer);
331
332 ready = 0;
333 }
334
335 #else
336
337260 ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp);
338
339 #endif
340261
341262 if (ready == -1) {
342263 err = ngx_socket_errno;
351272 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
352273 "select ready %d", ready);
353274
354 #if (NGX_WIN32)
355
356 if (err) {
357 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");
358
359 if (err == WSAENOTSOCK) {
360 ngx_select_repair_fd_sets(cycle);
361 }
362
363 return NGX_ERROR;
364 }
365
366 #else
367
368275 if (err) {
369276 ngx_uint_t level;
370277
389296
390297 return NGX_ERROR;
391298 }
392
393 #endif
394299
395300 if (ready == 0) {
396301 if (timer != NGX_TIMER_INFINITE) {
458363 ngx_err_t err;
459364 ngx_socket_t s;
460365
461 #if (NGX_WIN32)
462 u_int i;
463
464 for (i = 0; i < master_read_fd_set.fd_count; i++) {
465
466 s = master_read_fd_set.fd_array[i];
366 for (s = 0; s <= max_fd; s++) {
367
368 if (FD_ISSET(s, &master_read_fd_set) == 0) {
369 continue;
370 }
371
467372 len = sizeof(int);
468373
469 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
374 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) {
470375 err = ngx_socket_errno;
471376
472377 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
476381 }
477382 }
478383
479 for (i = 0; i < master_write_fd_set.fd_count; i++) {
480
481 s = master_write_fd_set.fd_array[i];
384 for (s = 0; s <= max_fd; s++) {
385
386 if (FD_ISSET(s, &master_write_fd_set) == 0) {
387 continue;
388 }
389
482390 len = sizeof(int);
483391
484 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
392 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) {
485393 err = ngx_socket_errno;
486394
487395 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
491399 }
492400 }
493401
494 #else
495
496 for (s = 0; s <= max_fd; s++) {
497
498 if (FD_ISSET(s, &master_read_fd_set) == 0) {
499 continue;
500 }
501
502 len = sizeof(int);
503
504 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) {
505 err = ngx_socket_errno;
506
507 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
508 "invalid descriptor #%d in read fd_set", s);
509
510 FD_CLR(s, &master_read_fd_set);
511 }
512 }
513
514 for (s = 0; s <= max_fd; s++) {
515
516 if (FD_ISSET(s, &master_write_fd_set) == 0) {
517 continue;
518 }
519
520 len = sizeof(int);
521
522 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) {
523 err = ngx_socket_errno;
524
525 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
526 "invalid descriptor #%d in write fd_set", s);
527
528 FD_CLR(s, &master_write_fd_set);
529 }
530 }
531
532402 max_fd = -1;
533
534 #endif
535403 }
536404
537405
547415 }
548416
549417 /* disable warning: the default FD_SETSIZE is 1024U in FreeBSD 5.x */
550
551 #if !(NGX_WIN32)
552418
553419 if (cycle->connection_n > FD_SETSIZE) {
554420 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
557423 return NGX_CONF_ERROR;
558424 }
559425
560 #endif
561
562 #if (NGX_THREADS) && !(NGX_WIN32)
426 #if (NGX_THREADS)
563427
564428 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
565429 "select() is not supported in the threaded mode");
0
1 /*
2 * Copyright (C) Igor Sysoev
3 */
4
5
6 #include <ngx_config.h>
7 #include <ngx_core.h>
8 #include <ngx_event.h>
9
10
11 static ngx_int_t ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer);
12 static void ngx_select_done(ngx_cycle_t *cycle);
13 static ngx_int_t ngx_select_add_event(ngx_event_t *ev, ngx_int_t event,
14 ngx_uint_t flags);
15 static ngx_int_t ngx_select_del_event(ngx_event_t *ev, ngx_int_t event,
16 ngx_uint_t flags);
17 static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
18 ngx_uint_t flags);
19 static void ngx_select_repair_fd_sets(ngx_cycle_t *cycle);
20 static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);
21
22
23 static fd_set master_read_fd_set;
24 static fd_set master_write_fd_set;
25 static fd_set work_read_fd_set;
26 static fd_set work_write_fd_set;
27
28 static ngx_uint_t max_read;
29 static ngx_uint_t max_write;
30 static ngx_uint_t nevents;
31
32 static ngx_event_t **event_index;
33
34
35 static ngx_str_t select_name = ngx_string("select");
36
37 ngx_event_module_t ngx_select_module_ctx = {
38 &select_name,
39 NULL, /* create configuration */
40 ngx_select_init_conf, /* init configuration */
41
42 {
43 ngx_select_add_event, /* add an event */
44 ngx_select_del_event, /* delete an event */
45 ngx_select_add_event, /* enable an event */
46 ngx_select_del_event, /* disable an event */
47 NULL, /* add an connection */
48 NULL, /* delete an connection */
49 NULL, /* process the changes */
50 ngx_select_process_events, /* process the events */
51 ngx_select_init, /* init the events */
52 ngx_select_done /* done the events */
53 }
54
55 };
56
57 ngx_module_t ngx_select_module = {
58 NGX_MODULE_V1,
59 &ngx_select_module_ctx, /* module context */
60 NULL, /* module directives */
61 NGX_EVENT_MODULE, /* module type */
62 NULL, /* init master */
63 NULL, /* init module */
64 NULL, /* init process */
65 NULL, /* init thread */
66 NULL, /* exit thread */
67 NULL, /* exit process */
68 NULL, /* exit master */
69 NGX_MODULE_V1_PADDING
70 };
71
72
73 static ngx_int_t
74 ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer)
75 {
76 ngx_event_t **index;
77
78 if (event_index == NULL) {
79 FD_ZERO(&master_read_fd_set);
80 FD_ZERO(&master_write_fd_set);
81 nevents = 0;
82 }
83
84 if (ngx_process == NGX_PROCESS_WORKER
85 || cycle->old_cycle == NULL
86 || cycle->old_cycle->connection_n < cycle->connection_n)
87 {
88 index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
89 cycle->log);
90 if (index == NULL) {
91 return NGX_ERROR;
92 }
93
94 if (event_index) {
95 ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents);
96 ngx_free(event_index);
97 }
98
99 event_index = index;
100 }
101
102 ngx_io = ngx_os_io;
103
104 ngx_event_actions = ngx_select_module_ctx.actions;
105
106 ngx_event_flags = NGX_USE_LEVEL_EVENT;
107
108 max_read = 0;
109 max_write = 0;
110
111 return NGX_OK;
112 }
113
114
115 static void
116 ngx_select_done(ngx_cycle_t *cycle)
117 {
118 ngx_free(event_index);
119
120 event_index = NULL;
121 }
122
123
124 static ngx_int_t
125 ngx_select_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
126 {
127 ngx_connection_t *c;
128
129 c = ev->data;
130
131 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
132 "select add event fd:%d ev:%i", c->fd, event);
133
134 if (ev->index != NGX_INVALID_INDEX) {
135 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
136 "select event fd:%d ev:%i is already set", c->fd, event);
137 return NGX_OK;
138 }
139
140 if ((event == NGX_READ_EVENT && ev->write)
141 || (event == NGX_WRITE_EVENT && !ev->write))
142 {
143 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
144 "invalid select %s event fd:%d ev:%i",
145 ev->write ? "write" : "read", c->fd, event);
146 return NGX_ERROR;
147 }
148
149 if ((event == NGX_READ_EVENT) && (max_read >= FD_SETSIZE)
150 || (event == NGX_WRITE_EVENT) && (max_write >= FD_SETSIZE))
151 {
152 ngx_log_error(NGX_LOG_ERR, ev->log, 0,
153 "maximum number of descriptors "
154 "supported by select() is %d", FD_SETSIZE);
155 return NGX_ERROR;
156 }
157
158 if (event == NGX_READ_EVENT) {
159 FD_SET(c->fd, &master_read_fd_set);
160 max_read++;
161
162 } else if (event == NGX_WRITE_EVENT) {
163 FD_SET(c->fd, &master_write_fd_set);
164 max_write++;
165 }
166
167 ev->active = 1;
168
169 event_index[nevents] = ev;
170 ev->index = nevents;
171 nevents++;
172
173 return NGX_OK;
174 }
175
176
177 static ngx_int_t
178 ngx_select_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
179 {
180 ngx_event_t *e;
181 ngx_connection_t *c;
182
183 c = ev->data;
184
185 ev->active = 0;
186
187 if (ev->index == NGX_INVALID_INDEX) {
188 return NGX_OK;
189 }
190
191 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
192 "select del event fd:%d ev:%i", c->fd, event);
193
194 if (event == NGX_READ_EVENT) {
195 FD_CLR(c->fd, &master_read_fd_set);
196 max_read--;
197
198 } else if (event == NGX_WRITE_EVENT) {
199 FD_CLR(c->fd, &master_write_fd_set);
200 max_write--;
201 }
202
203 if (ev->index < --nevents) {
204 e = event_index[nevents];
205 event_index[ev->index] = e;
206 e->index = ev->index;
207 }
208
209 ev->index = NGX_INVALID_INDEX;
210
211 return NGX_OK;
212 }
213
214
215 static ngx_int_t
216 ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
217 ngx_uint_t flags)
218 {
219 int ready, nready;
220 ngx_err_t err;
221 ngx_uint_t i, found;
222 ngx_event_t *ev, **queue;
223 struct timeval tv, *tp;
224 ngx_connection_t *c;
225
226 #if (NGX_DEBUG)
227 if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
228 for (i = 0; i < nevents; i++) {
229 ev = event_index[i];
230 c = ev->data;
231 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
232 "select event: fd:%d wr:%d", c->fd, ev->write);
233 }
234 }
235 #endif
236
237 if (timer == NGX_TIMER_INFINITE) {
238 tp = NULL;
239
240 } else {
241 tv.tv_sec = (long) (timer / 1000);
242 tv.tv_usec = (long) ((timer % 1000) * 1000);
243 tp = &tv;
244 }
245
246 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
247 "select timer: %M", timer);
248
249 work_read_fd_set = master_read_fd_set;
250 work_write_fd_set = master_write_fd_set;
251
252 if (max_read || max_write) {
253 ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);
254
255 } else {
256
257 /*
258 * Winsock select() requires that at least one descriptor set must be
259 * be non-null, and any non-null descriptor set must contain at least
260 * one handle to a socket. Otherwise select() returns WSAEINVAL.
261 */
262
263 ngx_msleep(timer);
264
265 ready = 0;
266 }
267
268 if (ready == -1) {
269 err = ngx_socket_errno;
270 } else {
271 err = 0;
272 }
273
274 if (flags & NGX_UPDATE_TIME) {
275 ngx_time_update(0, 0);
276 }
277
278 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
279 "select ready %d", ready);
280
281 if (err) {
282 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");
283
284 if (err == WSAENOTSOCK) {
285 ngx_select_repair_fd_sets(cycle);
286 }
287
288 return NGX_ERROR;
289 }
290
291 if (ready == 0) {
292 if (timer != NGX_TIMER_INFINITE) {
293 return NGX_OK;
294 }
295
296 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
297 "select() returned no events without timeout");
298 return NGX_ERROR;
299 }
300
301 ngx_mutex_lock(ngx_posted_events_mutex);
302
303 nready = 0;
304
305 for (i = 0; i < nevents; i++) {
306 ev = event_index[i];
307 c = ev->data;
308 found = 0;
309
310 if (ev->write) {
311 if (FD_ISSET(c->fd, &work_write_fd_set)) {
312 found = 1;
313 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
314 "select write %d", c->fd);
315 }
316
317 } else {
318 if (FD_ISSET(c->fd, &work_read_fd_set)) {
319 found = 1;
320 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
321 "select read %d", c->fd);
322 }
323 }
324
325 if (found) {
326 ev->ready = 1;
327
328 queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
329 &ngx_posted_events);
330 ngx_locked_post_event(ev, queue);
331
332 nready++;
333 }
334 }
335
336 ngx_mutex_unlock(ngx_posted_events_mutex);
337
338 if (ready != nready) {
339 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
340 "select ready != events: %d:%d", ready, nready);
341
342 ngx_select_repair_fd_sets(cycle);
343 }
344
345 return NGX_OK;
346 }
347
348
349 static void
350 ngx_select_repair_fd_sets(ngx_cycle_t *cycle)
351 {
352 int n;
353 u_int i;
354 socklen_t len;
355 ngx_err_t err;
356 ngx_socket_t s;
357
358 for (i = 0; i < master_read_fd_set.fd_count; i++) {
359
360 s = master_read_fd_set.fd_array[i];
361 len = sizeof(int);
362
363 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
364 err = ngx_socket_errno;
365
366 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
367 "invalid descriptor #%d in read fd_set", s);
368
369 FD_CLR(s, &master_read_fd_set);
370 }
371 }
372
373 for (i = 0; i < master_write_fd_set.fd_count; i++) {
374
375 s = master_write_fd_set.fd_array[i];
376 len = sizeof(int);
377
378 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
379 err = ngx_socket_errno;
380
381 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
382 "invalid descriptor #%d in write fd_set", s);
383
384 FD_CLR(s, &master_write_fd_set);
385 }
386 }
387 }
388
389
390 static char *
391 ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
392 {
393 ngx_event_conf_t *ecf;
394
395 ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
396
397 if (ecf->use != ngx_select_module.ctx_index) {
398 return NGX_CONF_OK;
399 }
400
401 return NGX_CONF_OK;
402 }