From 704407b01c6e6aa2ec71420d92158093011dc90f Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Mon, 24 May 2010 17:31:47 +0000 Subject: [PATCH] * WebCit thread pool is no longer tied to the number of server sessions. MIN_WORKER_THREADS is also gone. We now start with one worker thread. The only condition which causes new worker threads to be spawned is when all threads are executing and none are blocking on accept(). Initially this happens rather quickly, until the ideal thread pool size is found. --- webcit/context_loop.c | 21 +++++++++++---------- webcit/sysdep.c | 24 +++++++++++++++--------- webcit/webcit.h | 5 +++-- webcit/webserver.c | 9 ++------- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/webcit/context_loop.c b/webcit/context_loop.c index 1525e91a5..efa864f00 100644 --- a/webcit/context_loop.c +++ b/webcit/context_loop.c @@ -21,7 +21,10 @@ pthread_key_t MyConKey; /* TSD key for MySession() */ HashList *HttpReqTypes = NULL; HashList *HttpHeaderHandler = NULL; extern HashList *HandlerHash; -int num_threads = 1; /* Number of worker threads. Start at 1 because the parent counts. */ + +/* the following two values start at 1 because the initial parent thread counts as one. */ +int num_threads_existing = 1; /* Number of worker threads which exist. */ +int num_threads_executing = 1; /* Number of worker threads currently executing. */ void DestroyHttpHeaderHandler(void *V) { @@ -44,16 +47,13 @@ void do_housekeeping(void) { wcsession *sptr, *ss; wcsession *sessions_to_kill = NULL; - int num_sessions = 0; /* * Lock the session list, moving any candidates for euthanasia into * a separate list. */ pthread_mutex_lock(&SessionListMutex); - num_sessions = 0; for (sptr = SessionList; sptr != NULL; sptr = sptr->next) { - ++num_sessions; /* Kill idle sessions */ if ((time(NULL) - (sptr->lastreq)) > (time_t) WEBCIT_TIMEOUT) { @@ -90,18 +90,19 @@ void do_housekeeping(void) session_destroy_modules(&sessions_to_kill); sessions_to_kill = sptr; - --num_sessions; } /* - * If there are more sessions than threads, then we should spawn - * more threads ... up to a predefined maximum. + * Check the size of our thread pool. If all threads are executing, spawn another. */ - while ( (num_sessions > num_threads) && (num_threads <= MAX_WORKER_THREADS) ) { + begin_critical_section(S_SPAWNER); + while ( + (num_threads_executing >= num_threads_existing) + && (num_threads_existing <= MAX_WORKER_THREADS) + ) { spawn_another_worker_thread(); - lprintf(3, "There are %d sessions and %d threads active.\n", - num_sessions, num_threads); } + end_critical_section(S_SPAWNER); } diff --git a/webcit/sysdep.c b/webcit/sysdep.c index e2155814f..432966687 100644 --- a/webcit/sysdep.c +++ b/webcit/sysdep.c @@ -155,9 +155,10 @@ void worker_entry(void) ssock = -1; errno = EAGAIN; do { + --num_threads_executing; ssock = accept(msock, NULL, 0); + ++num_threads_executing; lprintf(9, "Thread %u woke up, accept() returned %d %s\n", - ((pthread_self() % 6) + 1), pthread_self(), ssock, ((ssock >= 0) ? "" : strerror(errno)) @@ -168,8 +169,8 @@ void worker_entry(void) {/* ok, we're going down. */ int shutdown = 0; - /* the first to come here will have to do the cleanup. - * make shure its realy just one. + /* The first thread to get here will have to do the cleanup. + * Make sure it's really just one. */ begin_critical_section(S_SHUTDOWN); if (msock == -1) @@ -198,15 +199,16 @@ void worker_entry(void) } if (ssock < 0 ) continue; + /* Now do something. */ if (msock < 0) { if (ssock > 0) close (ssock); - lprintf(2, "inbetween."); + lprintf(2, "in between."); pthread_exit(NULL); - } else { /* Got it? do some real work! */ + } else { + /* Got it? do some real work! */ /* Set the SO_REUSEADDR socket option */ i = 1; - setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, - &i, sizeof(i)); + setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); /* If we are an HTTPS server, go crypto now. */ #ifdef HAVE_OPENSSL @@ -244,8 +246,9 @@ void worker_entry(void) #endif /* ...and close the socket. */ - if (Hdr.http_sock > 0) + if (Hdr.http_sock > 0) { lingering_close(ssock); + } http_detach_modules(&Hdr); } @@ -422,7 +425,10 @@ void spawn_another_worker_thread() pthread_attr_t attr; /* Thread attributes */ int ret; - lprintf(3, "Creating a new thread. Pool size is now %d\n", ++num_threads); + lprintf(3, "Creating a new thread.\n"); + + ++num_threads_existing; + ++num_threads_executing; /* set attributes for the new thread */ pthread_attr_init(&attr); diff --git a/webcit/webcit.h b/webcit/webcit.h index b8f0d4e12..4e9442f44 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -134,7 +134,6 @@ extern char *ssl_cipher_list; #define DEFAULT_PORT "504" #define TARGET "webcit01" /* Target for inline URL's */ #define HOUSEKEEPING 15 /* Housekeeping frequency */ -#define MIN_WORKER_THREADS 5 #define MAX_WORKER_THREADS 250 #define LISTEN_QUEUE_LENGTH 100 /* listen() backlog queue */ @@ -588,6 +587,7 @@ void RegisterHeaderHandler(const char *Name, long Len, Header_Evaluator F); enum { S_SHUTDOWN, + S_SPAWNER, MAX_SEMAPHORES }; @@ -619,7 +619,8 @@ extern int is_https; extern int setup_wizard; extern char wizard_filename[]; extern int follow_xff; -extern int num_threads; +extern int num_threads_existing; +extern int num_threads_executing; void InitialiseSemaphores(void); void begin_critical_section(int which_one); diff --git a/webcit/webserver.c b/webcit/webserver.c index 97c1bfb12..243a29132 100644 --- a/webcit/webserver.c +++ b/webcit/webserver.c @@ -77,7 +77,7 @@ int main(int argc, char **argv) size_t basesize = 2; /* how big should strbufs be on creation? */ pthread_t SessThread; /* Thread descriptor */ pthread_attr_t attr; /* Thread attributes */ - int a, i; /* General-purpose variables */ + int a; /* General-purpose variable */ char tracefile[PATH_MAX]; char ip_addr[256]="0.0.0.0"; int relh=0; @@ -348,12 +348,7 @@ int main(int argc, char **argv) #endif drop_root(UID); - /* Start a few initial worker threads */ - for (i = 0; i < (MIN_WORKER_THREADS); ++i) { - spawn_another_worker_thread(); - } - - /* now the original thread becomes another worker */ + /* Become a worker thread. More worker threads will be spawned as they are needed. */ worker_entry(); ShutDownLibCitadel (); return 0; -- 2.30.2