From 14369bba1cc9d3dc85357ea9d64333b332703193 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Mon, 21 Feb 2005 19:58:39 +0000 Subject: [PATCH] * Misc changes to debug chat lockups * Dead session purge is now O(n) instead of O(something_larger) * Session binding for each transaction is faster too --- webcit/auth.c | 1 + webcit/context_loop.c | 114 ++++++++++++++++++++++-------------------- webcit/paging.c | 4 ++ webcit/tcp_sockets.c | 6 +-- webcit/webcit.c | 9 +++- 5 files changed, 76 insertions(+), 58 deletions(-) diff --git a/webcit/auth.c b/webcit/auth.c index 42c3c0a26..a5d87b08d 100644 --- a/webcit/auth.c +++ b/webcit/auth.c @@ -423,6 +423,7 @@ void changepw(void) serv_gets(buf); sprintf(WC->ImportantMessage, "%s", &buf[4]); if (buf[0] == '2') { + safestrncpy(WC->wc_password, buf, sizeof WC->wc_password); display_main_menu(); } else { diff --git a/webcit/context_loop.c b/webcit/context_loop.c index 387d63703..9389591d6 100644 --- a/webcit/context_loop.c +++ b/webcit/context_loop.c @@ -59,61 +59,67 @@ void free_attachments(struct wcsession *sess) { void do_housekeeping(void) { - struct wcsession *sptr, *ss, *session_to_kill; + struct wcsession *sptr, *ss; + struct wcsession *sessions_to_kill = NULL; int num_sessions = 0; static int num_threads = MIN_WORKER_THREADS; - do { - session_to_kill = NULL; - 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) { - sptr->killthis = 1; - } - - /* Remove sessions flagged for kill */ - if (sptr->killthis) { - - lprintf(3, "Destroying session %d\n", - sptr->wc_session); + /* + * 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) { + sptr->killthis = 1; + } - /* remove session from linked list */ - if (sptr == SessionList) { - SessionList = SessionList->next; - } - else for (ss=SessionList;ss!=NULL;ss=ss->next) { - if (ss->next == sptr) { - ss->next = ss->next->next; - } - } + /* Remove sessions flagged for kill */ + if (sptr->killthis) { - session_to_kill = sptr; - goto BREAKOUT; + /* remove session from linked list */ + if (sptr == SessionList) { + SessionList = SessionList->next; } - } -BREAKOUT: pthread_mutex_unlock(&SessionListMutex); - - if (session_to_kill != NULL) { - pthread_mutex_lock(&session_to_kill->SessionMutex); - close(session_to_kill->serv_sock); - close(session_to_kill->chat_sock); - if (session_to_kill->preferences != NULL) { - free(session_to_kill->preferences); + else for (ss=SessionList;ss!=NULL;ss=ss->next) { + if (ss->next == sptr) { + ss->next = ss->next->next; + } } - free_attachments(session_to_kill); - pthread_mutex_unlock(&session_to_kill->SessionMutex); - free(session_to_kill); + + sptr->next = sessions_to_kill; + sessions_to_kill = sptr; } + } + pthread_mutex_unlock(&SessionListMutex); - } while (session_to_kill != NULL); + /* + * Now free up and destroy the culled sessions. + */ + while (sessions_to_kill != NULL) { + lprintf(3, "Destroying session %d\n", sessions_to_kill->wc_session); + pthread_mutex_lock(&sessions_to_kill->SessionMutex); + close(sessions_to_kill->serv_sock); + close(sessions_to_kill->chat_sock); + if (sessions_to_kill->preferences != NULL) { + free(sessions_to_kill->preferences); + } + free_attachments(sessions_to_kill); + pthread_mutex_unlock(&sessions_to_kill->SessionMutex); + sptr = sessions_to_kill->next; + free(sessions_to_kill); + sessions_to_kill = sessions_to_kill->next; + --num_sessions; + } /* - * See if we need more worker threads + * If there are more sessions than threads, then we should spawn + * more threads ... up to a predefined maximum. */ while ( (num_sessions > num_threads) && (num_threads <= MAX_WORKER_THREADS) ) { @@ -357,23 +363,22 @@ void context_loop(int sock) */ TheSession = NULL; - if ( (TheSession == NULL) && (strlen(httpauth_user) > 0) ) { + if (TheSession == NULL) { pthread_mutex_lock(&SessionListMutex); for (sptr = SessionList; sptr != NULL; sptr = sptr->next) { - if ( (!strcasecmp(sptr->httpauth_user, httpauth_user)) + + /* If HTTP-AUTH, look for a session with matching credentials */ + if ( (strlen(httpauth_user) > 0) + &&(!strcasecmp(sptr->httpauth_user, httpauth_user)) &&(!strcasecmp(sptr->httpauth_pass, httpauth_pass)) ) { TheSession = sptr; } - } - pthread_mutex_unlock(&SessionListMutex); - } - if ( (TheSession == NULL) && (desired_session != 0) ) { - pthread_mutex_lock(&SessionListMutex); - for (sptr = SessionList; sptr != NULL; sptr = sptr->next) { - if (sptr->wc_session == desired_session) { + /* If cookie-session, look for a session with matching session ID */ + if ( (desired_session != 0) && (sptr->wc_session == desired_session)) { TheSession = sptr; } + } pthread_mutex_unlock(&SessionListMutex); } @@ -407,11 +412,14 @@ void context_loop(int sock) /* * Bind to the session and perform the transaction */ + lprintf(9, "LOCKING SESSION %d\n", TheSession->wc_session); pthread_mutex_lock(&TheSession->SessionMutex); /* bind */ + lprintf(9, "LOCKKED SESSION %d\n", TheSession->wc_session); pthread_setspecific(MyConKey, (void *)TheSession); TheSession->http_sock = sock; TheSession->lastreq = time(NULL); /* log */ session_loop(req); /* do transaction */ + lprintf(9, "UNLKING SESSION %d\n", TheSession->wc_session); pthread_mutex_unlock(&TheSession->SessionMutex); /* unbind */ /* Free the request buffer */ diff --git a/webcit/paging.c b/webcit/paging.c index c892b7a64..bc3fc936e 100644 --- a/webcit/paging.c +++ b/webcit/paging.c @@ -268,6 +268,7 @@ void chat_recv(void) { char cl_text[SIZ]; char *output_data = NULL; + lprintf(9, "chat_recv() called\n"); output_headers(0, 0, 0, 0, 0, 0, 0); wprintf("Content-type: text/html\n"); @@ -324,6 +325,7 @@ void chat_recv(void) { } while ( (got_data) && (!end_chat_now) ); if (end_chat_now) { + lprintf(9, "exiting chat\n"); close(WC->chat_sock); WC->chat_sock = (-1); wprintf("\n"); @@ -336,6 +338,7 @@ void chat_recv(void) { } /* Output our fun to the other frame. */ + lprintf(9, "output to other frame\n"); wprintf("\n"); + lprintf(9, "done fun\n"); } free(output_data); diff --git a/webcit/tcp_sockets.c b/webcit/tcp_sockets.c index 6752c5957..240e8e4c7 100644 --- a/webcit/tcp_sockets.c +++ b/webcit/tcp_sockets.c @@ -7,8 +7,8 @@ /* * Uncomment this to log all communications with the Citadel server -#define SERV_TRACE 1 */ +#define SERV_TRACE 1 #include #include @@ -178,7 +178,7 @@ void serv_gets(char *strbuf) if (strbuf[len-1] == 10) strbuf[--len] = 0; if (strbuf[len-1] == 13) strbuf[--len] = 0; #ifdef SERV_TRACE - lprintf(9, ">%s\n", strbuf); + lprintf(9, "%3d>%s\n", WC->serv_sock, strbuf); #endif } @@ -216,7 +216,7 @@ void serv_puts(char *string) char buf[SIZ]; #ifdef SERV_TRACE - lprintf(9, "<%s\n", string); + lprintf(9, "%3d<%s\n", WC->serv_sock, string); #endif sprintf(buf, "%s\n", string); serv_write(buf, strlen(buf)); diff --git a/webcit/webcit.c b/webcit/webcit.c index 91362db58..1339e33ae 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -451,9 +451,11 @@ void check_for_instant_messages() { char buf[SIZ]; + lprintf(9, "Checking for instant messages...\n"); serv_puts("NOOP"); serv_gets(buf); if (buf[3] == '*') WC->HaveInstantMessages = 1; + lprintf(9, "...done\n"); } @@ -1050,8 +1052,6 @@ void session_loop(struct httprequest *req) goto SKIP_ALL_THIS_CRAP; } - check_for_instant_messages(); - /* * If we're not logged in, but we have username and password cookies * supplied by the browser, try using them to log in. @@ -1081,6 +1081,11 @@ void session_loop(struct httprequest *req) } } + /* + * If there are instant messages waiting, retrieve them for display. + */ + check_for_instant_messages(); + if (!strcasecmp(action, "image")) { output_image(); -- 2.30.2