even more APIs for timeout and improved timeout handling

This commit is contained in:
Christian Grothoff
2007-08-15 08:36:06 +00:00
parent c9c5dfbefd
commit d8211f1b22
3 changed files with 90 additions and 9 deletions
+72 -9
View File
@@ -125,17 +125,21 @@ MHD_get_fdset (struct MHD_Daemon *daemon,
fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
{
struct MHD_Connection *pos;
int fd;
fd = daemon->socket_fd;
if ((daemon == NULL) ||
(read_fd_set == NULL) ||
(write_fd_set == NULL) ||
(except_fd_set == NULL) ||
(max_fd == NULL) ||
(fd == -1) ||
(daemon->shutdown == MHD_YES) ||
((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0))
return MHD_NO;
FD_SET (daemon->socket_fd, read_fd_set);
if ((*max_fd) < daemon->socket_fd)
*max_fd = daemon->socket_fd;
FD_SET (fd, read_fd_set);
if ((*max_fd) < fd)
*max_fd = fd;
pos = daemon->connections;
while (pos != NULL)
{
@@ -352,6 +356,46 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
}
}
/**
* Obtain timeout value for select for this daemon
* (only needed if connection timeout is used). The
* returned value is how long select should at most
* block, not the timeout value set for connections.
*
* @param timeout set to the timeout (in milliseconds)
* @return MHD_YES on success, MHD_NO if timeouts are
* not used (or no connections exist that would
* necessiate the use of a timeout right now).
*/
int
MHD_get_timeout(struct MHD_Daemon * daemon,
unsigned long long * timeout) {
time_t earliest_deadline;
time_t now;
struct MHD_Connection *pos;
unsigned int dto;
dto = daemon->connection_timeout;
if (0 == dto)
return MHD_NO;
pos = daemon->connections;
if (pos == NULL)
return MHD_NO; /* no connections */
now = time(NULL);
/* start with conservative estimate */
earliest_deadline = now + dto;
while (pos != NULL)
{
if (earliest_deadline > pos->last_activity + dto)
earliest_deadline = pos->last_activity + dto;
pos = pos->next;
}
if (earliest_deadline < now)
*timeout = 0;
else
*timeout = (earliest_deadline - now);
return MHD_YES;
}
/**
* Main select call.
@@ -369,13 +413,16 @@ MHD_select (struct MHD_Daemon *daemon, int may_block)
fd_set es;
int max;
struct timeval timeout;
unsigned long long ltimeout;
int ds;
time_t now;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if (daemon == NULL)
if (daemon == NULL)
abort ();
if (daemon->shutdown == MHD_YES)
return MHD_NO;
FD_ZERO (&rs);
FD_ZERO (&ws);
FD_ZERO (&es);
@@ -391,10 +438,24 @@ MHD_select (struct MHD_Daemon *daemon, int may_block)
{
/* accept only, have one thread per connection */
max = daemon->socket_fd;
FD_SET (daemon->socket_fd, &rs);
if (max != -1)
FD_SET (max, &rs);
}
if (may_block == MHD_NO) {
timeout.tv_usec = 0;
timeout.tv_sec = 0;
} else {
/* ltimeout is in ms */
if (MHD_YES == MHD_get_timeout(daemon, &ltimeout)) {
timeout.tv_usec = (ltimeout % 1000) * 1000 * 1000;
timeout.tv_sec = ltimeout / 1000;
may_block = MHD_NO;
}
}
num_ready = SELECT (max + 1,
&rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL);
if (daemon->shutdown == MHD_YES)
return MHD_NO;
if (num_ready < 0)
{
if (errno == EINTR)
@@ -448,7 +509,7 @@ MHD_select (struct MHD_Daemon *daemon, int may_block)
int
MHD_run (struct MHD_Daemon *daemon)
{
if ((daemon->shutdown != 0) ||
if ((daemon->shutdown != MHD_NO) ||
(0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
(0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
return MHD_NO;
@@ -466,7 +527,7 @@ static void *
MHD_select_thread (void *cls)
{
struct MHD_Daemon *daemon = cls;
while (daemon->shutdown == 0)
while (daemon->shutdown == MHD_NO)
{
MHD_select (daemon, MHD_YES);
MHD_cleanup_connections (daemon);
@@ -609,12 +670,14 @@ void
MHD_stop_daemon (struct MHD_Daemon *daemon)
{
void *unused;
int fd;
if (daemon == NULL)
return;
daemon->shutdown = 1;
CLOSE (daemon->socket_fd);
daemon->shutdown = MHD_YES;
fd = daemon->socket_fd;
daemon->socket_fd = -1;
CLOSE (fd);
if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
(0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
{
+2
View File
@@ -321,11 +321,13 @@ int
main (int argc, char *const *argv)
{
unsigned int errorCount = 0;
// int i;
oneone = NULL != strstr (argv[0], "11");
if (0 != curl_global_init (CURL_GLOBAL_WIN32))
return 2;
errorCount += testInternalGet ();
// for (i=0;i<10000;i++)
errorCount += testMultithreadedGet ();
errorCount += testExternalGet ();
if (errorCount != 0)
+16
View File
@@ -485,6 +485,22 @@ MHD_get_fdset (struct MHD_Daemon *daemon,
fd_set * read_fd_set,
fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd);
/**
* Obtain timeout value for select for this daemon
* (only needed if connection timeout is used). The
* returned value is how long select should at most
* block, not the timeout value set for connections.
*
* @param timeout set to the timeout (in milliseconds)
* @return MHD_YES on success, MHD_NO if timeouts are
* not used (or no connections exist that would
* necessiate the use of a timeout right now).
*/
int
MHD_get_timeout(struct MHD_Daemon * daemon,
unsigned long long * timeout);
/**
* Run webserver operations (without blocking unless
* in client callbacks). This method should be called