comparison src/event/modules/ngx_select_module.c @ 112:408f195b3482 NGINX_0_3_3

nginx 0.3.3 *) Change: the "bl" and "af" parameters of the "listen" directive was renamed to the "backlog" and "accept_filter". *) Feature: the "rcvbuf" and "sndbuf" parameters of the "listen" directive. *) Change: the "$msec" log parameter does not require now the additional the gettimeofday() system call. *) Feature: the -t switch now tests the "listen" directives. *) Bugfix: if the invalid address was specified in the "listen" directive, then after the -HUP signal nginx left an open socket in the CLOSED state. *) Bugfix: the mime type may be incorrectly set to default value for index file with variable in the name; bug appeared in 0.3.0. *) Feature: the "timer_resolution" directive. *) Feature: the millisecond "$upstream_response_time" log parameter. *) Bugfix: a temporary file with client request body now is removed just after the response header was transferred to a client. *) Bugfix: OpenSSL 0.9.6 compatibility. *) Bugfix: the SSL certificate and key file paths could not be relative. *) Bugfix: the "ssl_prefer_server_ciphers" directive did not work in the ngx_imap_ssl_module. *) Bugfix: the "ssl_protocols" directive allowed to specify the single protocol only.
author Igor Sysoev <http://sysoev.ru>
date Wed, 19 Oct 2005 00:00:00 +0400
parents 45f7329b4bd0
children e38f51cd0905
comparison
equal deleted inserted replaced
111:a175b609c76d 112:408f195b3482
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 10
11 11
12 12
13 static ngx_int_t ngx_select_init(ngx_cycle_t *cycle); 13 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); 14 static void ngx_select_done(ngx_cycle_t *cycle);
15 static ngx_int_t ngx_select_add_event(ngx_event_t *ev, int event, u_int flags); 15 static ngx_int_t ngx_select_add_event(ngx_event_t *ev, int event, u_int flags);
16 static ngx_int_t ngx_select_del_event(ngx_event_t *ev, int event, u_int flags); 16 static ngx_int_t ngx_select_del_event(ngx_event_t *ev, int event, u_int flags);
17 static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle); 17 static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
18 ngx_uint_t flags);
18 static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf); 19 static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);
19 20
20 21
21 static fd_set master_read_fd_set; 22 static fd_set master_read_fd_set;
22 static fd_set master_write_fd_set; 23 static fd_set master_write_fd_set;
31 #endif 32 #endif
32 33
33 static ngx_uint_t nevents; 34 static ngx_uint_t nevents;
34 35
35 static ngx_event_t **event_index; 36 static ngx_event_t **event_index;
36 #if 0
37 static ngx_event_t **ready_index;
38 #endif
39
40 static ngx_event_t *accept_events;
41 37
42 38
43 static ngx_str_t select_name = ngx_string("select"); 39 static ngx_str_t select_name = ngx_string("select");
44 40
45 ngx_event_module_t ngx_select_module_ctx = { 41 ngx_event_module_t ngx_select_module_ctx = {
77 NGX_MODULE_V1_PADDING 73 NGX_MODULE_V1_PADDING
78 }; 74 };
79 75
80 76
81 static ngx_int_t 77 static ngx_int_t
82 ngx_select_init(ngx_cycle_t *cycle) 78 ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer)
83 { 79 {
84 ngx_event_t **index; 80 ngx_event_t **index;
85 81
86 if (event_index == NULL) { 82 if (event_index == NULL) {
87 FD_ZERO(&master_read_fd_set); 83 FD_ZERO(&master_read_fd_set);
101 97
102 if (event_index) { 98 if (event_index) {
103 ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents); 99 ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents);
104 ngx_free(event_index); 100 ngx_free(event_index);
105 } 101 }
102
106 event_index = index; 103 event_index = index;
107
108 #if 0
109 if (ready_index) {
110 ngx_free(ready_index);
111 }
112
113 ready_index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
114 cycle->log);
115 if (ready_index == NULL) {
116 return NGX_ERROR;
117 }
118 #endif
119 } 104 }
120 105
121 ngx_io = ngx_os_io; 106 ngx_io = ngx_os_io;
122 107
123 ngx_event_actions = ngx_select_module_ctx.actions; 108 ngx_event_actions = ngx_select_module_ctx.actions;
124 109
125 ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT; 110 ngx_event_flags = NGX_USE_LEVEL_EVENT;
126 111
127 #if (NGX_WIN32) 112 #if (NGX_WIN32)
128 max_read = max_write = 0; 113 max_read = max_write = 0;
129 #else 114 #else
130 max_fd = -1; 115 max_fd = -1;
136 121
137 static void 122 static void
138 ngx_select_done(ngx_cycle_t *cycle) 123 ngx_select_done(ngx_cycle_t *cycle)
139 { 124 {
140 ngx_free(event_index); 125 ngx_free(event_index);
141 #if 0
142 ngx_free(ready_index);
143 #endif
144 126
145 event_index = NULL; 127 event_index = NULL;
146 } 128 }
147 129
148 130
260 return NGX_OK; 242 return NGX_OK;
261 } 243 }
262 244
263 245
264 static ngx_int_t 246 static ngx_int_t
265 ngx_select_process_events(ngx_cycle_t *cycle) 247 ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
266 { 248 ngx_uint_t flags)
267 int ready, nready; 249 {
268 ngx_uint_t i, found, lock; 250 int ready, nready;
269 ngx_err_t err; 251 ngx_uint_t i, found;
270 ngx_msec_t timer, delta; 252 ngx_err_t err;
271 ngx_event_t *ev; 253 ngx_msec_t delta;
272 ngx_connection_t *c; 254 ngx_event_t *ev, **queue;
273 struct timeval tv, *tp; 255 ngx_connection_t *c;
274 #if (NGX_HAVE_SELECT_CHANGE_TIMEOUT) 256 struct timeval tv, *tp;
275 static ngx_msec_t deltas = 0;
276 #endif
277
278 timer = ngx_event_find_timer();
279
280 #if !(NGX_WIN32) 257 #if !(NGX_WIN32)
281 258 ngx_uint_t level;
282 if (ngx_accept_mutex) { 259 #endif
283 if (ngx_accept_disabled > 0) { 260
284 ngx_accept_disabled--; 261 #if !(NGX_WIN32)
285
286 } else {
287 if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
288 return NGX_ERROR;
289 }
290
291 if (ngx_accept_mutex_held == 0
292 && (timer == NGX_TIMER_INFINITE
293 || timer > ngx_accept_mutex_delay))
294 {
295 timer = ngx_accept_mutex_delay;
296 }
297 }
298 }
299 262
300 if (max_fd == -1) { 263 if (max_fd == -1) {
301 for (i = 0; i < nevents; i++) { 264 for (i = 0; i < nevents; i++) {
302 c = event_index[i]->data; 265 c = event_index[i]->data;
303 if (max_fd < c->fd) { 266 if (max_fd < c->fd) {
351 "select read fd_set: %08Xd", 314 "select read fd_set: %08Xd",
352 *(int *) (void *) &work_read_fd_set); 315 *(int *) (void *) &work_read_fd_set);
353 #endif 316 #endif
354 317
355 #if (NGX_WIN32) 318 #if (NGX_WIN32)
319
356 ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp); 320 ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);
357 #else 321
322 #else
323
358 ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp); 324 ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp);
325
359 #endif 326 #endif
360 327
361 if (ready == -1) { 328 if (ready == -1) {
362 err = ngx_socket_errno; 329 err = ngx_socket_errno;
363 } else { 330 } else {
364 err = 0; 331 err = 0;
365 } 332 }
366 333
367 #if (NGX_HAVE_SELECT_CHANGE_TIMEOUT) 334 delta = ngx_current_msec;
335
336 if (flags & NGX_UPDATE_TIME) {
337 ngx_time_update(0, 0);
338 }
368 339
369 if (timer != NGX_TIMER_INFINITE) { 340 if (timer != NGX_TIMER_INFINITE) {
370 delta = timer - ((ngx_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000); 341 delta = ngx_current_msec - delta;
371
372 /*
373 * learn the real time and update the cached time
374 * if the sum of the last deltas overcomes 1 second
375 */
376
377 deltas += delta;
378 if (deltas > 1000) {
379 ngx_gettimeofday(&tv);
380 ngx_time_update(tv.tv_sec);
381 deltas = tv.tv_usec / 1000;
382
383 ngx_current_time = (ngx_msec_t) tv.tv_sec * 1000
384 + tv.tv_usec / 1000;
385 } else {
386 ngx_current_time += delta;
387 }
388
389 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
390 "select timer: %M, delta: %M", timer, delta);
391
392 } else {
393 deltas = 0;
394
395 ngx_gettimeofday(&tv);
396 ngx_time_update(tv.tv_sec);
397
398 delta = ngx_current_time;
399 ngx_current_time = (ngx_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000;
400
401 if (ready == 0) {
402 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
403 "select() returned no events without timeout");
404 ngx_accept_mutex_unlock();
405 return NGX_ERROR;
406 }
407 }
408
409 #else /* !(NGX_HAVE_SELECT_CHANGE_TIMEOUT) */
410
411 ngx_gettimeofday(&tv);
412 ngx_time_update(tv.tv_sec);
413
414 delta = ngx_current_time;
415 ngx_current_time = (ngx_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000;
416
417 if (timer != NGX_TIMER_INFINITE) {
418 delta = ngx_current_time - delta;
419 342
420 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, 343 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
421 "select timer: %M, delta: %M", timer, delta); 344 "select timer: %M, delta: %M", timer, delta);
422 345
423 } else { 346 } else {
424 if (ready == 0) { 347 if (ready == 0) {
425 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, 348 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
426 "select() returned no events without timeout"); 349 "select() returned no events without timeout");
427 ngx_accept_mutex_unlock();
428 return NGX_ERROR; 350 return NGX_ERROR;
429 } 351 }
430 } 352 }
431
432 #endif /* NGX_HAVE_SELECT_CHANGE_TIMEOUT */
433 353
434 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, 354 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
435 "select ready %d", ready); 355 "select ready %d", ready);
436 356
357 #if (NGX_WIN32)
358
437 if (err) { 359 if (err) {
438 #if (NGX_WIN32)
439 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed"); 360 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");
440 #else
441 ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
442 cycle->log, err, "select() failed");
443 #endif
444 ngx_accept_mutex_unlock();
445 return NGX_ERROR; 361 return NGX_ERROR;
446 } 362 }
447 363
448 364 #else
449 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { 365
450 ngx_accept_mutex_unlock(); 366 if (err) {
367 if (err == NGX_EINTR) {
368
369 if (ngx_event_timer_alarm) {
370 ngx_event_timer_alarm = 0;
371 return NGX_OK;
372 }
373
374 level = NGX_LOG_INFO;
375
376 } else {
377 level = NGX_LOG_ALERT;
378 }
379
380 ngx_log_error(level, cycle->log, err, "select() failed");
451 return NGX_ERROR; 381 return NGX_ERROR;
452 } 382 }
453 383
454 lock = 1; 384 #endif
385
386 if (nevents == 0) {
387 return NGX_OK;
388 }
389
390 ngx_mutex_lock(ngx_posted_events_mutex);
391
455 nready = 0; 392 nready = 0;
456 393
457 for (i = 0; i < nevents; i++) { 394 for (i = 0; i < nevents; i++) {
458 ev = event_index[i]; 395 ev = event_index[i];
459 c = ev->data; 396 c = ev->data;
475 } 412 }
476 413
477 if (found) { 414 if (found) {
478 ev->ready = 1; 415 ev->ready = 1;
479 416
480 if (ev->oneshot) { 417 queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
481 if (ev->timer_set) { 418 &ngx_posted_events);
482 ngx_del_timer(ev); 419 ngx_locked_post_event(ev, queue);
483 }
484
485 if (ev->write) {
486 ngx_select_del_event(ev, NGX_WRITE_EVENT, 0);
487 } else {
488 ngx_select_del_event(ev, NGX_READ_EVENT, 0);
489 }
490 }
491
492 if (ev->accept) {
493 ev->next = accept_events;
494 accept_events = ev;
495 } else {
496 ngx_post_event(ev);
497 }
498 420
499 nready++; 421 nready++;
500 422 }
501 #if 0 423 }
502 ready_index[nready++] = ev; 424
503 #endif 425 ngx_mutex_unlock(ngx_posted_events_mutex);
504 }
505 }
506
507 #if 0
508 for (i = 0; i < nready; i++) {
509 ev = ready_index[i];
510 ready--;
511
512 if (!ev->active) {
513 continue;
514 }
515
516 ev->ready = 1;
517
518 if (ev->oneshot) {
519 if (ev->timer_set) {
520 ngx_del_timer(ev);
521 }
522
523 if (ev->write) {
524 ngx_select_del_event(ev, NGX_WRITE_EVENT, 0);
525 } else {
526 ngx_select_del_event(ev, NGX_READ_EVENT, 0);
527 }
528 }
529
530 ev->handler(ev);
531 }
532 #endif
533
534 ev = accept_events;
535
536 for ( ;; ) {
537
538 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
539 "accept event %p", ev);
540
541 if (ev == NULL) {
542 break;
543 }
544
545 ngx_mutex_unlock(ngx_posted_events_mutex);
546
547 ev->handler(ev);
548
549 if (ngx_accept_disabled > 0) {
550 lock = 0;
551 break;
552 }
553
554 ev = ev->next;
555
556 if (ev == NULL) {
557 lock = 0;
558 break;
559 }
560
561 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
562 ngx_accept_mutex_unlock();
563 return NGX_ERROR;
564 }
565 }
566
567 ngx_accept_mutex_unlock();
568 accept_events = NULL;
569
570 if (lock) {
571 ngx_mutex_unlock(ngx_posted_events_mutex);
572 }
573 426
574 if (ready != nready) { 427 if (ready != nready) {
575 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events"); 428 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events");
576 } 429 }
577 430
578 ngx_event_expire_timers();
579
580 if (!ngx_threaded) {
581 ngx_event_process_posted(cycle);
582 }
583
584 return NGX_OK; 431 return NGX_OK;
585 } 432 }
586 433
587 434
588 static char * 435 static char *
597 } 444 }
598 445
599 /* disable warning: the default FD_SETSIZE is 1024U in FreeBSD 5.x */ 446 /* disable warning: the default FD_SETSIZE is 1024U in FreeBSD 5.x */
600 447
601 #if !(NGX_WIN32) 448 #if !(NGX_WIN32)
449
602 if ((unsigned) ecf->connections > FD_SETSIZE) { 450 if ((unsigned) ecf->connections > FD_SETSIZE) {
603 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, 451 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
604 "the maximum number of files " 452 "the maximum number of files "
605 "supported by select() is " ngx_value(FD_SETSIZE)); 453 "supported by select() is " ngx_value(FD_SETSIZE));
606 return NGX_CONF_ERROR; 454 return NGX_CONF_ERROR;
607 } 455 }
456
608 #endif 457 #endif
609 458
610 #if (NGX_THREADS) && !(NGX_WIN32) 459 #if (NGX_THREADS) && !(NGX_WIN32)
460
611 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, 461 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
612 "select() is not supported in the threaded mode"); 462 "select() is not supported in the threaded mode");
613 return NGX_CONF_ERROR; 463 return NGX_CONF_ERROR;
614 #else 464
465 #else
466
615 return NGX_CONF_OK; 467 return NGX_CONF_OK;
616 #endif 468
617 } 469 #endif
470 }