Mercurial > hg > nginx-quic
comparison src/event/modules/ngx_select_module.c @ 2813:c00763aa5e1b
divide select module into two modules: Unix and Win32 ones
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Wed, 06 May 2009 14:53:54 +0000 |
parents | be08552a64bf |
children | a66d6dfd53f1 e1409e56ba7c |
comparison
equal
deleted
inserted
replaced
2812:dcb1b4d6ff54 | 2813:c00763aa5e1b |
---|---|
5 | 5 |
6 | 6 |
7 #include <ngx_config.h> | 7 #include <ngx_config.h> |
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_event.h> | 9 #include <ngx_event.h> |
10 | |
11 | 10 |
12 | 11 |
13 static ngx_int_t ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer); | 12 static ngx_int_t ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer); |
14 static void ngx_select_done(ngx_cycle_t *cycle); | 13 static void ngx_select_done(ngx_cycle_t *cycle); |
15 static ngx_int_t ngx_select_add_event(ngx_event_t *ev, ngx_int_t event, | 14 static ngx_int_t ngx_select_add_event(ngx_event_t *ev, ngx_int_t event, |
25 static fd_set master_read_fd_set; | 24 static fd_set master_read_fd_set; |
26 static fd_set master_write_fd_set; | 25 static fd_set master_write_fd_set; |
27 static fd_set work_read_fd_set; | 26 static fd_set work_read_fd_set; |
28 static fd_set work_write_fd_set; | 27 static fd_set work_write_fd_set; |
29 | 28 |
30 #if (NGX_WIN32) | |
31 static ngx_uint_t max_read; | |
32 static ngx_uint_t max_write; | |
33 #else | |
34 static ngx_int_t max_fd; | 29 static ngx_int_t max_fd; |
35 #endif | |
36 | |
37 static ngx_uint_t nevents; | 30 static ngx_uint_t nevents; |
38 | 31 |
39 static ngx_event_t **event_index; | 32 static ngx_event_t **event_index; |
40 | 33 |
41 | 34 |
110 | 103 |
111 ngx_event_actions = ngx_select_module_ctx.actions; | 104 ngx_event_actions = ngx_select_module_ctx.actions; |
112 | 105 |
113 ngx_event_flags = NGX_USE_LEVEL_EVENT; | 106 ngx_event_flags = NGX_USE_LEVEL_EVENT; |
114 | 107 |
115 #if (NGX_WIN32) | |
116 max_read = max_write = 0; | |
117 #else | |
118 max_fd = -1; | 108 max_fd = -1; |
119 #endif | |
120 | 109 |
121 return NGX_OK; | 110 return NGX_OK; |
122 } | 111 } |
123 | 112 |
124 | 113 |
154 "invalid select %s event fd:%d ev:%i", | 143 "invalid select %s event fd:%d ev:%i", |
155 ev->write ? "write" : "read", c->fd, event); | 144 ev->write ? "write" : "read", c->fd, event); |
156 return NGX_ERROR; | 145 return NGX_ERROR; |
157 } | 146 } |
158 | 147 |
159 | |
160 #if (NGX_WIN32) | |
161 | |
162 if ((event == NGX_READ_EVENT) && (max_read >= FD_SETSIZE) | |
163 || (event == NGX_WRITE_EVENT) && (max_write >= FD_SETSIZE)) | |
164 { | |
165 ngx_log_error(NGX_LOG_ERR, ev->log, 0, | |
166 "maximum number of descriptors " | |
167 "supported by select() is %d", FD_SETSIZE); | |
168 return NGX_ERROR; | |
169 } | |
170 | |
171 if (event == NGX_READ_EVENT) { | 148 if (event == NGX_READ_EVENT) { |
172 FD_SET(c->fd, &master_read_fd_set); | 149 FD_SET(c->fd, &master_read_fd_set); |
173 max_read++; | |
174 | 150 |
175 } else if (event == NGX_WRITE_EVENT) { | 151 } else if (event == NGX_WRITE_EVENT) { |
176 FD_SET(c->fd, &master_write_fd_set); | 152 FD_SET(c->fd, &master_write_fd_set); |
177 max_write++; | |
178 } | |
179 | |
180 #else | |
181 | |
182 if (event == NGX_READ_EVENT) { | |
183 FD_SET(c->fd, &master_read_fd_set); | |
184 | |
185 } else if (event == NGX_WRITE_EVENT) { | |
186 FD_SET(c->fd, &master_write_fd_set); | |
187 } | 153 } |
188 | 154 |
189 if (max_fd != -1 && max_fd < c->fd) { | 155 if (max_fd != -1 && max_fd < c->fd) { |
190 max_fd = c->fd; | 156 max_fd = c->fd; |
191 } | 157 } |
192 | |
193 #endif | |
194 | 158 |
195 ev->active = 1; | 159 ev->active = 1; |
196 | 160 |
197 event_index[nevents] = ev; | 161 event_index[nevents] = ev; |
198 ev->index = nevents; | 162 ev->index = nevents; |
217 } | 181 } |
218 | 182 |
219 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, | 183 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, |
220 "select del event fd:%d ev:%i", c->fd, event); | 184 "select del event fd:%d ev:%i", c->fd, event); |
221 | 185 |
222 #if (NGX_WIN32) | |
223 | |
224 if (event == NGX_READ_EVENT) { | 186 if (event == NGX_READ_EVENT) { |
225 FD_CLR(c->fd, &master_read_fd_set); | 187 FD_CLR(c->fd, &master_read_fd_set); |
226 max_read--; | |
227 | 188 |
228 } else if (event == NGX_WRITE_EVENT) { | 189 } else if (event == NGX_WRITE_EVENT) { |
229 FD_CLR(c->fd, &master_write_fd_set); | 190 FD_CLR(c->fd, &master_write_fd_set); |
230 max_write--; | |
231 } | |
232 | |
233 #else | |
234 | |
235 if (event == NGX_READ_EVENT) { | |
236 FD_CLR(c->fd, &master_read_fd_set); | |
237 | |
238 } else if (event == NGX_WRITE_EVENT) { | |
239 FD_CLR(c->fd, &master_write_fd_set); | |
240 } | 191 } |
241 | 192 |
242 if (max_fd == c->fd) { | 193 if (max_fd == c->fd) { |
243 max_fd = -1; | 194 max_fd = -1; |
244 } | 195 } |
245 | |
246 #endif | |
247 | 196 |
248 if (ev->index < --nevents) { | 197 if (ev->index < --nevents) { |
249 e = event_index[nevents]; | 198 e = event_index[nevents]; |
250 event_index[ev->index] = e; | 199 event_index[ev->index] = e; |
251 e->index = ev->index; | 200 e->index = ev->index; |
266 ngx_uint_t i, found; | 215 ngx_uint_t i, found; |
267 ngx_event_t *ev, **queue; | 216 ngx_event_t *ev, **queue; |
268 struct timeval tv, *tp; | 217 struct timeval tv, *tp; |
269 ngx_connection_t *c; | 218 ngx_connection_t *c; |
270 | 219 |
271 #if !(NGX_WIN32) | |
272 | |
273 if (max_fd == -1) { | 220 if (max_fd == -1) { |
274 for (i = 0; i < nevents; i++) { | 221 for (i = 0; i < nevents; i++) { |
275 c = event_index[i]->data; | 222 c = event_index[i]->data; |
276 if (max_fd < c->fd) { | 223 if (max_fd < c->fd) { |
277 max_fd = c->fd; | 224 max_fd = c->fd; |
279 } | 226 } |
280 | 227 |
281 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 228 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
282 "change max_fd: %d", max_fd); | 229 "change max_fd: %d", max_fd); |
283 } | 230 } |
284 | |
285 #endif | |
286 | 231 |
287 #if (NGX_DEBUG) | 232 #if (NGX_DEBUG) |
288 if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) { | 233 if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) { |
289 for (i = 0; i < nevents; i++) { | 234 for (i = 0; i < nevents; i++) { |
290 ev = event_index[i]; | 235 ev = event_index[i]; |
291 c = ev->data; | 236 c = ev->data; |
292 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 237 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
293 "select event: fd:%d wr:%d", c->fd, ev->write); | 238 "select event: fd:%d wr:%d", c->fd, ev->write); |
294 } | 239 } |
295 | 240 |
296 #if !(NGX_WIN32) | |
297 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 241 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
298 "max_fd: %d", max_fd); | 242 "max_fd: %d", max_fd); |
299 #endif | |
300 } | 243 } |
301 #endif | 244 #endif |
302 | 245 |
303 if (timer == NGX_TIMER_INFINITE) { | 246 if (timer == NGX_TIMER_INFINITE) { |
304 tp = NULL; | 247 tp = NULL; |
313 "select timer: %M", timer); | 256 "select timer: %M", timer); |
314 | 257 |
315 work_read_fd_set = master_read_fd_set; | 258 work_read_fd_set = master_read_fd_set; |
316 work_write_fd_set = master_write_fd_set; | 259 work_write_fd_set = master_write_fd_set; |
317 | 260 |
318 #if (NGX_WIN32) | |
319 | |
320 if (max_read || max_write) { | |
321 ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp); | |
322 | |
323 } else { | |
324 | |
325 /* | |
326 * Winsock select() requires that at least one descriptor set must be | |
327 * be non-null, and any non-null descriptor set must contain at least | |
328 * one handle to a socket. Otherwise select() returns WSAEINVAL. | |
329 */ | |
330 | |
331 ngx_msleep(timer); | |
332 | |
333 ready = 0; | |
334 } | |
335 | |
336 #else | |
337 | |
338 ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp); | 261 ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp); |
339 | |
340 #endif | |
341 | 262 |
342 if (ready == -1) { | 263 if (ready == -1) { |
343 err = ngx_socket_errno; | 264 err = ngx_socket_errno; |
344 } else { | 265 } else { |
345 err = 0; | 266 err = 0; |
350 } | 271 } |
351 | 272 |
352 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 273 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
353 "select ready %d", ready); | 274 "select ready %d", ready); |
354 | 275 |
355 #if (NGX_WIN32) | |
356 | |
357 if (err) { | |
358 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed"); | |
359 | |
360 if (err == WSAENOTSOCK) { | |
361 ngx_select_repair_fd_sets(cycle); | |
362 } | |
363 | |
364 return NGX_ERROR; | |
365 } | |
366 | |
367 #else | |
368 | |
369 if (err) { | 276 if (err) { |
370 ngx_uint_t level; | 277 ngx_uint_t level; |
371 | 278 |
372 if (err == NGX_EINTR) { | 279 if (err == NGX_EINTR) { |
373 | 280 |
388 ngx_select_repair_fd_sets(cycle); | 295 ngx_select_repair_fd_sets(cycle); |
389 } | 296 } |
390 | 297 |
391 return NGX_ERROR; | 298 return NGX_ERROR; |
392 } | 299 } |
393 | |
394 #endif | |
395 | 300 |
396 if (ready == 0) { | 301 if (ready == 0) { |
397 if (timer != NGX_TIMER_INFINITE) { | 302 if (timer != NGX_TIMER_INFINITE) { |
398 return NGX_OK; | 303 return NGX_OK; |
399 } | 304 } |
457 int n; | 362 int n; |
458 socklen_t len; | 363 socklen_t len; |
459 ngx_err_t err; | 364 ngx_err_t err; |
460 ngx_socket_t s; | 365 ngx_socket_t s; |
461 | 366 |
462 #if (NGX_WIN32) | 367 for (s = 0; s <= max_fd; s++) { |
463 u_int i; | 368 |
464 | 369 if (FD_ISSET(s, &master_read_fd_set) == 0) { |
465 for (i = 0; i < master_read_fd_set.fd_count; i++) { | 370 continue; |
466 | 371 } |
467 s = master_read_fd_set.fd_array[i]; | 372 |
468 len = sizeof(int); | 373 len = sizeof(int); |
469 | 374 |
470 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) { | 375 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) { |
471 err = ngx_socket_errno; | 376 err = ngx_socket_errno; |
472 | 377 |
473 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, | 378 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, |
474 "invalid descriptor #%d in read fd_set", s); | 379 "invalid descriptor #%d in read fd_set", s); |
475 | 380 |
476 FD_CLR(s, &master_read_fd_set); | 381 FD_CLR(s, &master_read_fd_set); |
477 } | 382 } |
478 } | 383 } |
479 | 384 |
480 for (i = 0; i < master_write_fd_set.fd_count; i++) { | 385 for (s = 0; s <= max_fd; s++) { |
481 | 386 |
482 s = master_write_fd_set.fd_array[i]; | 387 if (FD_ISSET(s, &master_write_fd_set) == 0) { |
388 continue; | |
389 } | |
390 | |
483 len = sizeof(int); | 391 len = sizeof(int); |
484 | 392 |
485 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) { | 393 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) { |
486 err = ngx_socket_errno; | 394 err = ngx_socket_errno; |
487 | 395 |
488 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, | 396 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, |
489 "invalid descriptor #%d in write fd_set", s); | 397 "invalid descriptor #%d in write fd_set", s); |
490 | 398 |
491 FD_CLR(s, &master_write_fd_set); | 399 FD_CLR(s, &master_write_fd_set); |
492 } | 400 } |
493 } | 401 } |
494 | 402 |
495 #else | |
496 | |
497 for (s = 0; s <= max_fd; s++) { | |
498 | |
499 if (FD_ISSET(s, &master_read_fd_set) == 0) { | |
500 continue; | |
501 } | |
502 | |
503 len = sizeof(int); | |
504 | |
505 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) { | |
506 err = ngx_socket_errno; | |
507 | |
508 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, | |
509 "invalid descriptor #%d in read fd_set", s); | |
510 | |
511 FD_CLR(s, &master_read_fd_set); | |
512 } | |
513 } | |
514 | |
515 for (s = 0; s <= max_fd; s++) { | |
516 | |
517 if (FD_ISSET(s, &master_write_fd_set) == 0) { | |
518 continue; | |
519 } | |
520 | |
521 len = sizeof(int); | |
522 | |
523 if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) { | |
524 err = ngx_socket_errno; | |
525 | |
526 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, | |
527 "invalid descriptor #%d in write fd_set", s); | |
528 | |
529 FD_CLR(s, &master_write_fd_set); | |
530 } | |
531 } | |
532 | |
533 max_fd = -1; | 403 max_fd = -1; |
534 | |
535 #endif | |
536 } | 404 } |
537 | 405 |
538 | 406 |
539 static char * | 407 static char * |
540 ngx_select_init_conf(ngx_cycle_t *cycle, void *conf) | 408 ngx_select_init_conf(ngx_cycle_t *cycle, void *conf) |
546 if (ecf->use != ngx_select_module.ctx_index) { | 414 if (ecf->use != ngx_select_module.ctx_index) { |
547 return NGX_CONF_OK; | 415 return NGX_CONF_OK; |
548 } | 416 } |
549 | 417 |
550 /* disable warning: the default FD_SETSIZE is 1024U in FreeBSD 5.x */ | 418 /* disable warning: the default FD_SETSIZE is 1024U in FreeBSD 5.x */ |
551 | |
552 #if !(NGX_WIN32) | |
553 | 419 |
554 if (cycle->connection_n > FD_SETSIZE) { | 420 if (cycle->connection_n > FD_SETSIZE) { |
555 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, | 421 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, |
556 "the maximum number of files " | 422 "the maximum number of files " |
557 "supported by select() is %ud", FD_SETSIZE); | 423 "supported by select() is %ud", FD_SETSIZE); |
558 return NGX_CONF_ERROR; | 424 return NGX_CONF_ERROR; |
559 } | 425 } |
560 | 426 |
561 #endif | 427 #if (NGX_THREADS) |
562 | |
563 #if (NGX_THREADS) && !(NGX_WIN32) | |
564 | 428 |
565 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, | 429 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, |
566 "select() is not supported in the threaded mode"); | 430 "select() is not supported in the threaded mode"); |
567 return NGX_CONF_ERROR; | 431 return NGX_CONF_ERROR; |
568 | 432 |