diff options
author | Christian Grothoff <christian@grothoff.org> | 2007-08-15 08:36:06 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2007-08-15 08:36:06 +0000 |
commit | d8211f1b223bbfee1fbe42106efd7b8157308408 (patch) | |
tree | ce7bc0501711ef12222ffe49fb0b1e1d411ef8eb | |
parent | c9c5dfbefd0a3e219b17174fe43b51cdc0cabb67 (diff) | |
download | libmicrohttpd-d8211f1b223bbfee1fbe42106efd7b8157308408.tar.gz libmicrohttpd-d8211f1b223bbfee1fbe42106efd7b8157308408.zip |
even more APIs for timeout and improved timeout handling
-rw-r--r-- | src/daemon/daemon.c | 81 | ||||
-rw-r--r-- | src/daemon/daemontest_get.c | 2 | ||||
-rw-r--r-- | src/include/microhttpd.h | 16 |
3 files changed, 90 insertions, 9 deletions
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 0c198454..ac326b83 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c | |||
@@ -125,17 +125,21 @@ MHD_get_fdset (struct MHD_Daemon *daemon, | |||
125 | fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd) | 125 | fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd) |
126 | { | 126 | { |
127 | struct MHD_Connection *pos; | 127 | struct MHD_Connection *pos; |
128 | int fd; | ||
128 | 129 | ||
130 | fd = daemon->socket_fd; | ||
129 | if ((daemon == NULL) || | 131 | if ((daemon == NULL) || |
130 | (read_fd_set == NULL) || | 132 | (read_fd_set == NULL) || |
131 | (write_fd_set == NULL) || | 133 | (write_fd_set == NULL) || |
132 | (except_fd_set == NULL) || | 134 | (except_fd_set == NULL) || |
133 | (max_fd == NULL) || | 135 | (max_fd == NULL) || |
136 | (fd == -1) || | ||
137 | (daemon->shutdown == MHD_YES) || | ||
134 | ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)) | 138 | ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)) |
135 | return MHD_NO; | 139 | return MHD_NO; |
136 | FD_SET (daemon->socket_fd, read_fd_set); | 140 | FD_SET (fd, read_fd_set); |
137 | if ((*max_fd) < daemon->socket_fd) | 141 | if ((*max_fd) < fd) |
138 | *max_fd = daemon->socket_fd; | 142 | *max_fd = fd; |
139 | pos = daemon->connections; | 143 | pos = daemon->connections; |
140 | while (pos != NULL) | 144 | while (pos != NULL) |
141 | { | 145 | { |
@@ -352,6 +356,46 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) | |||
352 | } | 356 | } |
353 | } | 357 | } |
354 | 358 | ||
359 | /** | ||
360 | * Obtain timeout value for select for this daemon | ||
361 | * (only needed if connection timeout is used). The | ||
362 | * returned value is how long select should at most | ||
363 | * block, not the timeout value set for connections. | ||
364 | * | ||
365 | * @param timeout set to the timeout (in milliseconds) | ||
366 | * @return MHD_YES on success, MHD_NO if timeouts are | ||
367 | * not used (or no connections exist that would | ||
368 | * necessiate the use of a timeout right now). | ||
369 | */ | ||
370 | int | ||
371 | MHD_get_timeout(struct MHD_Daemon * daemon, | ||
372 | unsigned long long * timeout) { | ||
373 | time_t earliest_deadline; | ||
374 | time_t now; | ||
375 | struct MHD_Connection *pos; | ||
376 | unsigned int dto; | ||
377 | |||
378 | dto = daemon->connection_timeout; | ||
379 | if (0 == dto) | ||
380 | return MHD_NO; | ||
381 | pos = daemon->connections; | ||
382 | if (pos == NULL) | ||
383 | return MHD_NO; /* no connections */ | ||
384 | now = time(NULL); | ||
385 | /* start with conservative estimate */ | ||
386 | earliest_deadline = now + dto; | ||
387 | while (pos != NULL) | ||
388 | { | ||
389 | if (earliest_deadline > pos->last_activity + dto) | ||
390 | earliest_deadline = pos->last_activity + dto; | ||
391 | pos = pos->next; | ||
392 | } | ||
393 | if (earliest_deadline < now) | ||
394 | *timeout = 0; | ||
395 | else | ||
396 | *timeout = (earliest_deadline - now); | ||
397 | return MHD_YES; | ||
398 | } | ||
355 | 399 | ||
356 | /** | 400 | /** |
357 | * Main select call. | 401 | * Main select call. |
@@ -369,13 +413,16 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) | |||
369 | fd_set es; | 413 | fd_set es; |
370 | int max; | 414 | int max; |
371 | struct timeval timeout; | 415 | struct timeval timeout; |
416 | unsigned long long ltimeout; | ||
372 | int ds; | 417 | int ds; |
373 | time_t now; | 418 | time_t now; |
374 | 419 | ||
375 | timeout.tv_sec = 0; | 420 | timeout.tv_sec = 0; |
376 | timeout.tv_usec = 0; | 421 | timeout.tv_usec = 0; |
377 | if (daemon == NULL) | 422 | if (daemon == NULL) |
378 | abort (); | 423 | abort (); |
424 | if (daemon->shutdown == MHD_YES) | ||
425 | return MHD_NO; | ||
379 | FD_ZERO (&rs); | 426 | FD_ZERO (&rs); |
380 | FD_ZERO (&ws); | 427 | FD_ZERO (&ws); |
381 | FD_ZERO (&es); | 428 | FD_ZERO (&es); |
@@ -391,10 +438,24 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) | |||
391 | { | 438 | { |
392 | /* accept only, have one thread per connection */ | 439 | /* accept only, have one thread per connection */ |
393 | max = daemon->socket_fd; | 440 | max = daemon->socket_fd; |
394 | FD_SET (daemon->socket_fd, &rs); | 441 | if (max != -1) |
442 | FD_SET (max, &rs); | ||
395 | } | 443 | } |
444 | if (may_block == MHD_NO) { | ||
445 | timeout.tv_usec = 0; | ||
446 | timeout.tv_sec = 0; | ||
447 | } else { | ||
448 | /* ltimeout is in ms */ | ||
449 | if (MHD_YES == MHD_get_timeout(daemon, <imeout)) { | ||
450 | timeout.tv_usec = (ltimeout % 1000) * 1000 * 1000; | ||
451 | timeout.tv_sec = ltimeout / 1000; | ||
452 | may_block = MHD_NO; | ||
453 | } | ||
454 | } | ||
396 | num_ready = SELECT (max + 1, | 455 | num_ready = SELECT (max + 1, |
397 | &rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL); | 456 | &rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL); |
457 | if (daemon->shutdown == MHD_YES) | ||
458 | return MHD_NO; | ||
398 | if (num_ready < 0) | 459 | if (num_ready < 0) |
399 | { | 460 | { |
400 | if (errno == EINTR) | 461 | if (errno == EINTR) |
@@ -448,7 +509,7 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) | |||
448 | int | 509 | int |
449 | MHD_run (struct MHD_Daemon *daemon) | 510 | MHD_run (struct MHD_Daemon *daemon) |
450 | { | 511 | { |
451 | if ((daemon->shutdown != 0) || | 512 | if ((daemon->shutdown != MHD_NO) || |
452 | (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || | 513 | (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || |
453 | (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))) | 514 | (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))) |
454 | return MHD_NO; | 515 | return MHD_NO; |
@@ -466,7 +527,7 @@ static void * | |||
466 | MHD_select_thread (void *cls) | 527 | MHD_select_thread (void *cls) |
467 | { | 528 | { |
468 | struct MHD_Daemon *daemon = cls; | 529 | struct MHD_Daemon *daemon = cls; |
469 | while (daemon->shutdown == 0) | 530 | while (daemon->shutdown == MHD_NO) |
470 | { | 531 | { |
471 | MHD_select (daemon, MHD_YES); | 532 | MHD_select (daemon, MHD_YES); |
472 | MHD_cleanup_connections (daemon); | 533 | MHD_cleanup_connections (daemon); |
@@ -609,12 +670,14 @@ void | |||
609 | MHD_stop_daemon (struct MHD_Daemon *daemon) | 670 | MHD_stop_daemon (struct MHD_Daemon *daemon) |
610 | { | 671 | { |
611 | void *unused; | 672 | void *unused; |
673 | int fd; | ||
612 | 674 | ||
613 | if (daemon == NULL) | 675 | if (daemon == NULL) |
614 | return; | 676 | return; |
615 | daemon->shutdown = 1; | 677 | daemon->shutdown = MHD_YES; |
616 | CLOSE (daemon->socket_fd); | 678 | fd = daemon->socket_fd; |
617 | daemon->socket_fd = -1; | 679 | daemon->socket_fd = -1; |
680 | CLOSE (fd); | ||
618 | if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || | 681 | if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || |
619 | (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))) | 682 | (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))) |
620 | { | 683 | { |
diff --git a/src/daemon/daemontest_get.c b/src/daemon/daemontest_get.c index daea7a39..01612dfa 100644 --- a/src/daemon/daemontest_get.c +++ b/src/daemon/daemontest_get.c | |||
@@ -321,11 +321,13 @@ int | |||
321 | main (int argc, char *const *argv) | 321 | main (int argc, char *const *argv) |
322 | { | 322 | { |
323 | unsigned int errorCount = 0; | 323 | unsigned int errorCount = 0; |
324 | // int i; | ||
324 | 325 | ||
325 | oneone = NULL != strstr (argv[0], "11"); | 326 | oneone = NULL != strstr (argv[0], "11"); |
326 | if (0 != curl_global_init (CURL_GLOBAL_WIN32)) | 327 | if (0 != curl_global_init (CURL_GLOBAL_WIN32)) |
327 | return 2; | 328 | return 2; |
328 | errorCount += testInternalGet (); | 329 | errorCount += testInternalGet (); |
330 | // for (i=0;i<10000;i++) | ||
329 | errorCount += testMultithreadedGet (); | 331 | errorCount += testMultithreadedGet (); |
330 | errorCount += testExternalGet (); | 332 | errorCount += testExternalGet (); |
331 | if (errorCount != 0) | 333 | if (errorCount != 0) |
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index 76c1be0b..ec08318d 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -486,6 +486,22 @@ MHD_get_fdset (struct MHD_Daemon *daemon, | |||
486 | fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd); | 486 | fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd); |
487 | 487 | ||
488 | /** | 488 | /** |
489 | * Obtain timeout value for select for this daemon | ||
490 | * (only needed if connection timeout is used). The | ||
491 | * returned value is how long select should at most | ||
492 | * block, not the timeout value set for connections. | ||
493 | * | ||
494 | * @param timeout set to the timeout (in milliseconds) | ||
495 | * @return MHD_YES on success, MHD_NO if timeouts are | ||
496 | * not used (or no connections exist that would | ||
497 | * necessiate the use of a timeout right now). | ||
498 | */ | ||
499 | int | ||
500 | MHD_get_timeout(struct MHD_Daemon * daemon, | ||
501 | unsigned long long * timeout); | ||
502 | |||
503 | |||
504 | /** | ||
489 | * Run webserver operations (without blocking unless | 505 | * Run webserver operations (without blocking unless |
490 | * in client callbacks). This method should be called | 506 | * in client callbacks). This method should be called |
491 | * by clients in combination with MHD_get_fdset | 507 | * by clients in combination with MHD_get_fdset |