Fixed the bug that prevented DOWN from working properly.
authorDave West <davew@uncensored.citadel.org>
Sun, 1 Nov 2009 18:09:14 +0000 (18:09 +0000)
committerDave West <davew@uncensored.citadel.org>
Sun, 1 Nov 2009 18:09:14 +0000 (18:09 +0000)
Also broke the context handling routines out of sysdep.c and other places
and put them in context.c / .h
This has been done to make it easier to improve the speed with which we
create / destroy contexts and threads.

14 files changed:
citadel/Makefile.in
citadel/citserver.c
citadel/citserver.h
citadel/context.c [new file with mode: 0644]
citadel/context.h [new file with mode: 0644]
citadel/modules/checkpoint/serv_checkpoint.c
citadel/modules/expire/serv_expire.c
citadel/modules/fulltext/serv_fulltext.c
citadel/modules/network/serv_network.c
citadel/modules/rssclient/serv_rssclient.c
citadel/server_main.c
citadel/sysdep.c
citadel/sysdep_decls.h
citadel/threads.c

index e062692368ce6ea3c3cd1b66177c15e518394f63..cb952e569a6a3f91a7fc104db1c11d6b99ee041c 100644 (file)
@@ -86,7 +86,8 @@ SOURCES=utils/aidepost.c utils/stress.c utils/whobbs.c utils/citmail.c \
        housekeeping.c ical_dezonify.c internet_addressing.c ecrash.c \
        locate_host.c md5.c auth.c msgbase.c parsedate.c policy.c \
        room_ops.c euidindex.c server_main.c snprintf.c ldap.c \
-       support.c sysdep.c user_ops.c journaling.c threads.c 
+       support.c sysdep.c user_ops.c journaling.c threads.c \
+       context.c
 
 
 include Make_sources
@@ -153,7 +154,7 @@ SERV_OBJS = server_main.o utillib/citadel_dirs.o\
        file_ops.o msgbase.o euidindex.o \
        locate_host.o housekeeping.o \
        internet_addressing.o journaling.o \
-       parsedate.o genstamp.o ecrash.o threads.o\
+       parsedate.o genstamp.o ecrash.o threads.o context.o \
        clientsocket.o modules_init.o modules_upgrade.o $(AUTH) $(SERV_MODULES) \
        svn_revision.o ldap.o
 
index 2f5f24690fa0b0277967e9344db044c48c9a3632..e8e310f0d40082d88c569262e69e293d6c7e9f42 100644 (file)
@@ -73,6 +73,7 @@
 #include "policy.h"
 #include "control.h"
 #include "euidindex.h"
+#include "context.h"
 #include "svn_revision.h"
 
 #ifndef HAVE_SNPRINTF
@@ -82,8 +83,6 @@
 #include "ctdl_module.h"
 
 
-struct CitContext *ContextList = NULL;
-struct CitContext* next_session = NULL;
 char *unique_session_numbers;
 int ScheduledShutdown = 0;
 time_t server_startup_time;
@@ -251,46 +250,6 @@ void master_cleanup(int exitcode) {
 
 
 
-/*
- * Terminate a session.
- */
-void RemoveContext (struct CitContext *con)
-{
-       if (con==NULL) {
-               CtdlLogPrintf(CTDL_ERR,
-                       "WARNING: RemoveContext() called with NULL!\n");
-               return;
-       }
-       CtdlLogPrintf(CTDL_DEBUG, "RemoveContext() session %d\n", con->cs_pid);
-
-       /* Run any cleanup routines registered by loadable modules.
-        * Note: We have to "become_session()" because the cleanup functions
-        *       might make references to "CC" assuming it's the right one.
-        */
-       become_session(con);
-       logout();
-       PerformSessionHooks(EVT_STOP);
-       become_session(NULL);
-
-       CtdlLogPrintf(CTDL_NOTICE, "[%3d] Session ended.\n", con->cs_pid);
-
-       /* If the client is still connected, blow 'em away. */
-       CtdlLogPrintf(CTDL_DEBUG, "Closing socket %d\n", con->client_socket);
-       close(con->client_socket);
-
-       /* If using AUTHMODE_LDAP, free the DN */
-       if (con->ldap_dn) {
-               free(con->ldap_dn);
-               con->ldap_dn = NULL;
-       }
-
-       CtdlLogPrintf(CTDL_DEBUG, "Done with RemoveContext()\n");
-}
-
-
-
-
-
 /*
  * cmd_info()  -  tell the client about this server
  */
@@ -873,6 +832,7 @@ void cmd_down(char *argbuf) {
        {
                cprintf(Reply, CIT_OK + SERVER_SHUTTING_DOWN); 
        }
+       CC->kill_me = 1; /* Even the DOWN command has to follow correct proceedure when disconecting */
        CtdlThreadStopAll();
 }
 
index 3e9ead3ecf3470d0f8405c86109013e28ac760b0..1eb8cd8042a5d129b17b09603b67d5724abd414f 100644 (file)
@@ -33,7 +33,6 @@ void cit_backtrace(void);
 void cit_panic_backtrace(int SigNum);
 void master_startup (void);
 void master_cleanup (int exitcode);
-void RemoveContext (struct CitContext *);
 void set_wtmpsupp (char *newtext);
 void set_wtmpsupp_to_current_room(void);
 void do_command_loop(void);
diff --git a/citadel/context.c b/citadel/context.c
new file mode 100644 (file)
index 0000000..4985de9
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * $Id: sysdep.c 7989 2009-10-31 15:29:37Z davew $
+ *
+ * Citadel context management stuff.
+ * See COPYING for copyright information.
+ *
+ * Here's where we (hopefully) have all the code that manipulates contexts.
+ *
+ */
+
+#include "sysdep.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <syslog.h>
+#include <sys/syslog.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include <limits.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/un.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <grp.h>
+#include <libcitadel.h>
+#include "citadel.h"
+#include "server.h"
+#include "sysdep_decls.h"
+#include "citserver.h"
+#include "support.h"
+#include "config.h"
+#include "database.h"
+#include "housekeeping.h"
+#include "modules/crypto/serv_crypto.h"        /* Needed for init_ssl, client_write_ssl, client_read_ssl, destruct_ssl */
+#include "ecrash.h"
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifndef HAVE_SNPRINTF
+#include "snprintf.h"
+#endif
+
+#include "ctdl_module.h"
+#include "threads.h"
+#include "user_ops.h"
+#include "control.h"
+
+
+
+citthread_key_t MyConKey;                              /* TSD key for MyContext() */
+
+
+struct CitContext masterCC;
+struct CitContext *ContextList = NULL;
+// struct CitContext* next_session = NULL;
+
+time_t last_purge = 0;                         /* Last dead session purge */
+int num_sessions = 0;                          /* Current number of sessions */
+
+/* Flag for single user mode */
+static int want_single_user = 0;
+
+/* Try to go single user */
+
+int CtdlTrySingleUser(void)
+{
+       int can_do = 0;
+       
+       begin_critical_section(S_SINGLE_USER);
+       if (want_single_user)
+               can_do = 0;
+       else
+       {
+               can_do = 1;
+               want_single_user = 1;
+       }
+       end_critical_section(S_SINGLE_USER);
+       return can_do;
+}
+
+void CtdlEndSingleUser(void)
+{
+       begin_critical_section(S_SINGLE_USER);
+       want_single_user = 0;
+       end_critical_section(S_SINGLE_USER);
+}
+
+
+int CtdlWantSingleUser(void)
+{
+       return want_single_user;
+}
+
+int CtdlIsSingleUser(void)
+{
+       if (want_single_user)
+       {
+               /* check for only one context here */
+               if (num_sessions == 1)
+                       return TRUE;
+       }
+       return FALSE;
+}
+
+
+/*
+ * Return a pointer to the CitContext structure bound to the thread which
+ * called this function.  If there's no such binding (for example, if it's
+ * called by the housekeeper thread) then a generic 'master' CC is returned.
+ *
+ * This function is used *VERY* frequently and must be kept small.
+ */
+struct CitContext *MyContext(void) {
+
+       register struct CitContext *c;
+
+       return ((c = (struct CitContext *) citthread_getspecific(MyConKey),
+               c == NULL) ? &masterCC : c
+       );
+}
+
+
+
+
+/*
+ * Terminate a session.
+ */
+void RemoveContext (struct CitContext *con)
+{
+       if (con==NULL) {
+               CtdlLogPrintf(CTDL_ERR,
+                       "WARNING: RemoveContext() called with NULL!\n");
+               return;
+       }
+       CtdlLogPrintf(CTDL_DEBUG, "RemoveContext() session %d\n", con->cs_pid);
+
+       /* Run any cleanup routines registered by loadable modules.
+        * Note: We have to "become_session()" because the cleanup functions
+        *       might make references to "CC" assuming it's the right one.
+        */
+       become_session(con);
+       logout();
+       PerformSessionHooks(EVT_STOP);
+       become_session(NULL);
+
+       CtdlLogPrintf(CTDL_NOTICE, "[%3d] Session ended.\n", con->cs_pid);
+
+       /* If the client is still connected, blow 'em away. */
+       CtdlLogPrintf(CTDL_DEBUG, "Closing socket %d\n", con->client_socket);
+       close(con->client_socket);
+
+       /* If using AUTHMODE_LDAP, free the DN */
+       if (con->ldap_dn) {
+               free(con->ldap_dn);
+               con->ldap_dn = NULL;
+       }
+
+       CtdlLogPrintf(CTDL_DEBUG, "Done with RemoveContext()\n");
+}
+
+
+
+
+
+/*
+ * Initialize a new context and place it in the list.  The session number
+ * used to be the PID (which is why it's called cs_pid), but that was when we
+ * had one process per session.  Now we just assign them sequentially, starting
+ * at 1 (don't change it to 0 because masterCC uses 0).
+ */
+struct CitContext *CreateNewContext(void) {
+       struct CitContext *me;
+       static int next_pid = 0;
+
+       me = (struct CitContext *) malloc(sizeof(struct CitContext));
+       if (me == NULL) {
+               CtdlLogPrintf(CTDL_ALERT, "citserver: can't allocate memory!!\n");
+               return NULL;
+       }
+
+       memset(me, 0, sizeof(struct CitContext));
+       
+       /* Give the contaxt a name. Hopefully makes it easier to track */
+       strcpy (me->user.fullname, "SYS_notauth");
+       
+       /* The new context will be created already in the CON_EXECUTING state
+        * in order to prevent another thread from grabbing it while it's
+        * being set up.
+        */
+       me->state = CON_EXECUTING;
+       /*
+        * Generate a unique session number and insert this context into
+        * the list.
+        */
+       begin_critical_section(S_SESSION_TABLE);
+       me->cs_pid = ++next_pid;
+       me->prev = NULL;
+       me->next = ContextList;
+       ContextList = me;
+       if (me->next != NULL) {
+               me->next->prev = me;
+       }
+       ++num_sessions;
+       end_critical_section(S_SESSION_TABLE);
+       return (me);
+}
+
+
+struct CitContext *CtdlGetContextArray(int *count)
+{
+       int nContexts, i;
+       struct CitContext *nptr, *cptr;
+       
+       nContexts = num_sessions;
+       nptr = malloc(sizeof(struct CitContext) * nContexts);
+       if (!nptr)
+               return NULL;
+       begin_critical_section(S_SESSION_TABLE);
+       for (cptr = ContextList, i=0; cptr != NULL && i < nContexts; cptr = cptr->next, i++)
+               memcpy(&nptr[i], cptr, sizeof (struct CitContext));
+       end_critical_section (S_SESSION_TABLE);
+       
+       *count = i;
+       return nptr;
+}
+
+
+
+/**
+ * This function fills in a context and its user field correctly
+ * Then creates/loads that user
+ */
+void CtdlFillSystemContext(struct CitContext *context, char *name)
+{
+       char sysname[USERNAME_SIZE];
+
+       memset(context, 0, sizeof(struct CitContext));
+       context->internal_pgm = 1;
+       context->cs_pid = 0;
+       strcpy (sysname, "SYS_");
+       strcat (sysname, name);
+       /* internal_create_user has the side effect of loading the user regardless of wether they
+        * already existed or needed to be created
+        */
+       internal_create_user (sysname, &(context->user), -1) ;
+       
+       /* Check to see if the system user needs upgrading */
+       if (context->user.usernum == 0)
+       {       /* old system user with number 0, upgrade it */
+               context->user.usernum = get_new_user_number();
+               CtdlLogPrintf(CTDL_DEBUG, "Upgrading system user \"%s\" from user number 0 to user number %d\n", context->user.fullname, context->user.usernum);
+               /* add user to the database */
+               CtdlPutUser(&(context->user));
+               cdb_store(CDB_USERSBYNUMBER, &(context->user.usernum), sizeof(long), context->user.fullname, strlen(context->user.fullname)+1);
+       }
+}
+
+/*
+ * Cleanup any contexts that are left lying around
+ */
+void context_cleanup(void)
+{
+       struct CitContext *ptr = NULL;
+       struct CitContext *rem = NULL;
+
+       /*
+        * Clean up the contexts.
+        * There are no threads so no critical_section stuff is needed.
+        */
+       ptr = ContextList;
+       
+       /* We need to update the ContextList because some modules may want to itterate it
+        * Question is should we NULL it before iterating here or should we just keep updating it
+        * as we remove items?
+        *
+        * Answer is to NULL it first to prevent modules from doing any actions on the list at all
+        */
+       ContextList=NULL;
+       while (ptr != NULL){
+               /* Remove the session from the active list */
+               rem = ptr->next;
+               --num_sessions;
+               
+               CtdlLogPrintf(CTDL_DEBUG, "Purging session %d\n", ptr->cs_pid);
+               RemoveContext(ptr);
+               free (ptr);
+               ptr = rem;
+       }
+}
+
+
+
+/*
+ * Terminate another session.
+ * (This could justifiably be moved out of sysdep.c because it
+ * no longer does anything that is system-dependent.)
+ */
+void kill_session(int session_to_kill) {
+       struct CitContext *ptr;
+
+       begin_critical_section(S_SESSION_TABLE);
+       for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
+               if (ptr->cs_pid == session_to_kill) {
+                       ptr->kill_me = 1;
+               }
+       }
+       end_critical_section(S_SESSION_TABLE);
+}
+
+/*
+ * Purge all sessions which have the 'kill_me' flag set.
+ * This function has code to prevent it from running more than once every
+ * few seconds, because running it after every single unbind would waste a lot
+ * of CPU time and keep the context list locked too much.  To force it to run
+ * anyway, set "force" to nonzero.
+ */
+void dead_session_purge(int force) {
+       struct CitContext *ptr, *ptr2;          /* general-purpose utility pointer */
+       struct CitContext *rem = NULL;  /* list of sessions to be destroyed */
+       
+       if (force == 0) {
+               if ( (time(NULL) - last_purge) < 5 ) {
+                       return; /* Too soon, go away */
+               }
+       }
+       time(&last_purge);
+
+       if (try_critical_section(S_SESSION_TABLE))
+               return;
+               
+       ptr = ContextList;
+       while (ptr) {
+               ptr2 = ptr;
+               ptr = ptr->next;
+               
+               if ( (ptr2->state == CON_IDLE) && (ptr2->kill_me) ) {
+                       /* Remove the session from the active list */
+                       if (ptr2->prev) {
+                               ptr2->prev->next = ptr2->next;
+                       }
+                       else {
+                               ContextList = ptr2->next;
+                       }
+                       if (ptr2->next) {
+                               ptr2->next->prev = ptr2->prev;
+                       }
+
+                       --num_sessions;
+                       /* And put it on our to-be-destroyed list */
+                       ptr2->next = rem;
+                       rem = ptr2;
+               }
+       }
+       end_critical_section(S_SESSION_TABLE);
+
+       /* Now that we no longer have the session list locked, we can take
+        * our time and destroy any sessions on the to-be-killed list, which
+        * is allocated privately on this thread's stack.
+        */
+       while (rem != NULL) {
+               CtdlLogPrintf(CTDL_DEBUG, "Purging session %d\n", rem->cs_pid);
+               RemoveContext(rem);
+               ptr = rem;
+               rem = rem->next;
+               free(ptr);
+       }
+}
+
+
+
+
+
+/*
+ * masterCC is the context we use when not attached to a session.  This
+ * function initializes it.
+ */
+void InitializeMasterCC(void) {
+       memset(&masterCC, 0, sizeof(struct CitContext));
+       masterCC.internal_pgm = 1;
+       masterCC.cs_pid = 0;
+}
+
+
+
+
+/*
+ * Bind a thread to a context.  (It's inline merely to speed things up.)
+ */
+INLINE void become_session(struct CitContext *which_con) {
+       citthread_setspecific(MyConKey, (void *)which_con );
+}
+
+
+
diff --git a/citadel/context.h b/citadel/context.h
new file mode 100644 (file)
index 0000000..b136f53
--- /dev/null
@@ -0,0 +1,28 @@
+/* $Id: sysdep_decls.h 7265 2009-03-25 23:18:46Z dothebart $ */
+
+#ifndef CONTEXT_H
+#define CONTEXT_H
+
+#include <stdarg.h>
+#include "sysdep.h"
+#include "server.h"
+#include "sysdep_decls.h"
+#include "threads.h"
+
+
+extern citthread_key_t MyConKey;                       /* TSD key for MyContext() */
+extern int num_sessions;
+extern struct CitContext masterCC;
+
+struct CitContext *MyContext (void);
+void RemoveContext (struct CitContext *);
+struct CitContext *CreateNewContext (void);
+void context_cleanup(void);
+void kill_session (int session_to_kill);
+INLINE void become_session(struct CitContext *which_con);
+void InitializeMasterCC(void);
+void dead_session_purge(int force);
+
+
+
+#endif /* CONTEXT_H */
index f94a41dc341993e0c36b543835953e6f9fc77895..da04ac4b906eaa542c9e57c183f744260569a18e 100644 (file)
@@ -56,6 +56,7 @@
 #include "threads.h"
 
 #include "ctdl_module.h"
+#include "context.h"
  
 /*
  * Main loop for the checkpoint thread.
index b0824e2fb23fea28011c13e7803b028421b400f5..94e716216d68f44291652d084b333e0f06770d9c 100644 (file)
@@ -82,6 +82,7 @@
 #include "control.h"
 #include "serv_network.h"      /* Needed for definition of UseTable */
 #include "threads.h"
+#include "context.h"
 
 #include "ctdl_module.h"
 
index 68f5f4136785fee740cba71cc19eb6a084e18ad5..b52d959e954a5de7856ff70f0338d18fc02cd29d 100644 (file)
@@ -58,6 +58,7 @@
 #include "serv_fulltext.h"
 #include "ft_wordbreaker.h"
 #include "threads.h"
+#include "context.h"
 
 #include "ctdl_module.h"
 
index dddf90b47fa9e7d5e0ae5562451432759b4a84f3..b289851dc979264281a14c5c0a8bdb2283a8100a 100644 (file)
@@ -82,6 +82,7 @@
 #include "snprintf.h"
 #endif
 
+#include "context.h"
 
 #include "ctdl_module.h"
 
index e60c5ad9448d39fe8437cf2813a24744000537a7..b1610d67b0d0eb6b969a6525309408d2ab3dd22f 100644 (file)
@@ -56,6 +56,7 @@
 #include "database.h"
 #include "citadel_dirs.h"
 #include "md5.h"
+#include "context.h"
 
 
 struct rssnetcfg {
index 71f81feb398936e5499db698ebcc6451e099641d..5d73d7a523ceb3899839e031bafb80e8c653365f 100644 (file)
@@ -57,6 +57,8 @@
 #include "svn_revision.h"
 #include "citadel_dirs.h"
 
+#include "context.h"
+
 #include "modules_init.h"
 #include "ecrash.h"
 
@@ -71,8 +73,6 @@ const char *CitadelServiceUDS="citadel-UDS";
 const char *CitadelServiceTCP="citadel-TCP";
 
 
-extern struct CitContext masterCC;
-
 
 void go_threading(void);
 
index 433f3467b1e8a659d566f168945917bbd174aa60..3ddc662aa549ca65b29d22242ea6c9e66708220c 100644 (file)
@@ -60,6 +60,7 @@
 #include "housekeeping.h"
 #include "modules/crypto/serv_crypto.h"        /* Needed for init_ssl, client_write_ssl, client_read_ssl, destruct_ssl */
 #include "ecrash.h"
+#include "context.h"
 
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
@@ -87,64 +88,12 @@ struct igheap *igheap = NULL;
 #endif
 
 
-citthread_key_t MyConKey;                              /* TSD key for MyContext() */
-
 int verbosity = DEFAULT_VERBOSITY;             /* Logging level */
 
-struct CitContext masterCC;
-time_t last_purge = 0;                         /* Last dead session purge */
-int num_sessions = 0;                          /* Current number of sessions */
-
 int syslog_facility = LOG_DAEMON;
 int enable_syslog = 0;
 
 
-/* Flag for single user mode */
-static int want_single_user = 0;
-
-/* Try to go single user */
-
-int CtdlTrySingleUser(void)
-{
-       int can_do = 0;
-       
-       begin_critical_section(S_SINGLE_USER);
-       if (want_single_user)
-               can_do = 0;
-       else
-       {
-               can_do = 1;
-               want_single_user = 1;
-       }
-       end_critical_section(S_SINGLE_USER);
-       return can_do;
-}
-
-void CtdlEndSingleUser(void)
-{
-       begin_critical_section(S_SINGLE_USER);
-       want_single_user = 0;
-       end_critical_section(S_SINGLE_USER);
-}
-
-
-int CtdlWantSingleUser(void)
-{
-       return want_single_user;
-}
-
-int CtdlIsSingleUser(void)
-{
-       if (want_single_user)
-       {
-               /* check for only one context here */
-               if (num_sessions == 1)
-                       return TRUE;
-       }
-       return FALSE;
-}
-
-
 /*
  * CtdlLogPrintf()  ...   Write logging information
  */
@@ -445,116 +394,6 @@ int ig_uds_server(char *sockpath, int queue_len, char **errormessage)
 
 
 
-/*
- * Return a pointer to the CitContext structure bound to the thread which
- * called this function.  If there's no such binding (for example, if it's
- * called by the housekeeper thread) then a generic 'master' CC is returned.
- *
- * This function is used *VERY* frequently and must be kept small.
- */
-struct CitContext *MyContext(void) {
-
-       register struct CitContext *c;
-
-       return ((c = (struct CitContext *) citthread_getspecific(MyConKey),
-               c == NULL) ? &masterCC : c
-       );
-}
-
-
-/*
- * Initialize a new context and place it in the list.  The session number
- * used to be the PID (which is why it's called cs_pid), but that was when we
- * had one process per session.  Now we just assign them sequentially, starting
- * at 1 (don't change it to 0 because masterCC uses 0).
- */
-struct CitContext *CreateNewContext(void) {
-       struct CitContext *me;
-       static int next_pid = 0;
-
-       me = (struct CitContext *) malloc(sizeof(struct CitContext));
-       if (me == NULL) {
-               CtdlLogPrintf(CTDL_ALERT, "citserver: can't allocate memory!!\n");
-               return NULL;
-       }
-
-       memset(me, 0, sizeof(struct CitContext));
-       
-       /* Give the contaxt a name. Hopefully makes it easier to track */
-       strcpy (me->user.fullname, "SYS_notauth");
-       
-       /* The new context will be created already in the CON_EXECUTING state
-        * in order to prevent another thread from grabbing it while it's
-        * being set up.
-        */
-       me->state = CON_EXECUTING;
-       /*
-        * Generate a unique session number and insert this context into
-        * the list.
-        */
-       begin_critical_section(S_SESSION_TABLE);
-       me->cs_pid = ++next_pid;
-       me->prev = NULL;
-       me->next = ContextList;
-       ContextList = me;
-       if (me->next != NULL) {
-               me->next->prev = me;
-       }
-       ++num_sessions;
-       end_critical_section(S_SESSION_TABLE);
-       return (me);
-}
-
-
-struct CitContext *CtdlGetContextArray(int *count)
-{
-       int nContexts, i;
-       struct CitContext *nptr, *cptr;
-       
-       nContexts = num_sessions;
-       nptr = malloc(sizeof(struct CitContext) * nContexts);
-       if (!nptr)
-               return NULL;
-       begin_critical_section(S_SESSION_TABLE);
-       for (cptr = ContextList, i=0; cptr != NULL && i < nContexts; cptr = cptr->next, i++)
-               memcpy(&nptr[i], cptr, sizeof (struct CitContext));
-       end_critical_section (S_SESSION_TABLE);
-       
-       *count = i;
-       return nptr;
-}
-
-
-
-/**
- * This function fills in a context and its user field correctly
- * Then creates/loads that user
- */
-void CtdlFillSystemContext(struct CitContext *context, char *name)
-{
-       char sysname[USERNAME_SIZE];
-
-       memset(context, 0, sizeof(struct CitContext));
-       context->internal_pgm = 1;
-       context->cs_pid = 0;
-       strcpy (sysname, "SYS_");
-       strcat (sysname, name);
-       /* internal_create_user has the side effect of loading the user regardless of wether they
-        * already existed or needed to be created
-        */
-       internal_create_user (sysname, &(context->user), -1) ;
-       
-       /* Check to see if the system user needs upgrading */
-       if (context->user.usernum == 0)
-       {       /* old system user with number 0, upgrade it */
-               context->user.usernum = get_new_user_number();
-               CtdlLogPrintf(CTDL_DEBUG, "Upgrading system user \"%s\" from user number 0 to user number %d\n", context->user.fullname, context->user.usernum);
-               /* add user to the database */
-               CtdlPutUser(&(context->user));
-               cdb_store(CDB_USERSBYNUMBER, &(context->user.usernum), sizeof(long), context->user.fullname, strlen(context->user.fullname)+1);
-       }
-}
-
 /*
  * The following functions implement output buffering on operating systems which
  * support it (such as Linux and various BSD flavors).
@@ -792,36 +631,6 @@ int client_getln(char *buf, int bufsize)
 /*
  * Cleanup any contexts that are left lying around
  */
-void context_cleanup(void)
-{
-       struct CitContext *ptr = NULL;
-       struct CitContext *rem = NULL;
-
-       /*
-        * Clean up the contexts.
-        * There are no threads so no critical_section stuff is needed.
-        */
-       ptr = ContextList;
-       
-       /* We need to update the ContextList because some modules may want to itterate it
-        * Question is should we NULL it before iterating here or should we just keep updating it
-        * as we remove items?
-        *
-        * Answer is to NULL it first to prevent modules from doing any actions on the list at all
-        */
-       ContextList=NULL;
-       while (ptr != NULL){
-               /* Remove the session from the active list */
-               rem = ptr->next;
-               --num_sessions;
-               
-               CtdlLogPrintf(CTDL_DEBUG, "Purging session %d\n", ptr->cs_pid);
-               RemoveContext(ptr);
-               free (ptr);
-               ptr = rem;
-       }
-}
-
 
 
 void close_masters (void)
@@ -885,23 +694,6 @@ void sysdep_master_cleanup(void) {
 
 
 
-/*
- * Terminate another session.
- * (This could justifiably be moved out of sysdep.c because it
- * no longer does anything that is system-dependent.)
- */
-void kill_session(int session_to_kill) {
-       struct CitContext *ptr;
-
-       begin_critical_section(S_SESSION_TABLE);
-       for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
-               if (ptr->cs_pid == session_to_kill) {
-                       ptr->kill_me = 1;
-               }
-       }
-       end_critical_section(S_SESSION_TABLE);
-}
-
 pid_t current_child;
 void graceful_shutdown(int signum) {
        kill(current_child, signum);
@@ -1043,92 +835,6 @@ int convert_login(char NameToConvert[]) {
        }
 }
 
-/*
- * Purge all sessions which have the 'kill_me' flag set.
- * This function has code to prevent it from running more than once every
- * few seconds, because running it after every single unbind would waste a lot
- * of CPU time and keep the context list locked too much.  To force it to run
- * anyway, set "force" to nonzero.
- */
-void dead_session_purge(int force) {
-       struct CitContext *ptr, *ptr2;          /* general-purpose utility pointer */
-       struct CitContext *rem = NULL;  /* list of sessions to be destroyed */
-       
-       if (force == 0) {
-               if ( (time(NULL) - last_purge) < 5 ) {
-                       return; /* Too soon, go away */
-               }
-       }
-       time(&last_purge);
-
-       if (try_critical_section(S_SESSION_TABLE))
-               return;
-               
-       ptr = ContextList;
-       while (ptr) {
-               ptr2 = ptr;
-               ptr = ptr->next;
-               
-               if ( (ptr2->state == CON_IDLE) && (ptr2->kill_me) ) {
-                       /* Remove the session from the active list */
-                       if (ptr2->prev) {
-                               ptr2->prev->next = ptr2->next;
-                       }
-                       else {
-                               ContextList = ptr2->next;
-                       }
-                       if (ptr2->next) {
-                               ptr2->next->prev = ptr2->prev;
-                       }
-
-                       --num_sessions;
-                       /* And put it on our to-be-destroyed list */
-                       ptr2->next = rem;
-                       rem = ptr2;
-               }
-       }
-       end_critical_section(S_SESSION_TABLE);
-
-       /* Now that we no longer have the session list locked, we can take
-        * our time and destroy any sessions on the to-be-killed list, which
-        * is allocated privately on this thread's stack.
-        */
-       while (rem != NULL) {
-               CtdlLogPrintf(CTDL_DEBUG, "Purging session %d\n", rem->cs_pid);
-               RemoveContext(rem);
-               ptr = rem;
-               rem = rem->next;
-               free(ptr);
-       }
-}
-
-
-
-
-
-/*
- * masterCC is the context we use when not attached to a session.  This
- * function initializes it.
- */
-void InitializeMasterCC(void) {
-       memset(&masterCC, 0, sizeof(struct CitContext));
-       masterCC.internal_pgm = 1;
-       masterCC.cs_pid = 0;
-}
-
-
-
-
-/*
- * Bind a thread to a context.  (It's inline merely to speed things up.)
- */
-INLINE void become_session(struct CitContext *which_con) {
-       if (which_con)
-               ctdl_thread_internal_change_state(CT, CTDL_THREAD_RUNNING);
-
-       citthread_setspecific(MyConKey, (void *)which_con );
-}
-
 
 
 /* 
@@ -1189,7 +895,8 @@ do_select: force_purge = 0;
 
                begin_critical_section(S_SESSION_TABLE);
                for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
-                       if (ptr->state == CON_IDLE) {
+                       /* Dont select on dead sessions only truly idle ones */
+                       if ((ptr->state == CON_IDLE)) {
                                FD_SET(ptr->client_socket, &readfds);
                                if (ptr->client_socket > highest)
                                        highest = ptr->client_socket;
index 802ae3305df533dc778e528c3fc858db9886ffbd..3c463f755e699d444ae211c3385e6bb9aa87b500 100644 (file)
@@ -49,16 +49,11 @@ void cprintf (const char *format, ...);
 void CtdlLogPrintf(enum LogLevel loglevel, const char *format, ...);
 void vCtdlLogPrintf (enum LogLevel loglevel, const char *format, va_list arg_ptr);
 
-extern pthread_key_t MyConKey;                 /* TSD key for MyContext() */
-
 extern int enable_syslog;
 
 void init_sysdep (void);
 int ig_tcp_server (char *ip_addr, int port_number, int queue_len,char **errormessage);
 int ig_uds_server(char *sockpath, int queue_len, char **errormessage);
-struct CitContext *MyContext (void);
-struct CitContext *CreateNewContext (void);
-void InitMyContext (struct CitContext *con);
 void buffer_output(void);
 void unbuffer_output(void);
 void flush_output(void);
@@ -68,20 +63,15 @@ int client_read (char *buf, int bytes);
 int client_getln (char *buf, int maxbytes);
 void sysdep_master_cleanup (void);
 void kill_session (int session_to_kill);
-void *sd_context_loop (struct CitContext *con);
 void start_daemon (int do_close_stdio);
 void checkcrash(void);
 void cmd_nset (char *cmdbuf);
 int convert_login (char *NameToConvert);
 void *worker_thread (void *arg);
-void *context_cleanup_thread (void *arg);
-void become_session(struct CitContext *which_con);
-void InitializeMasterCC(void);
 void init_master_fdset(void);
 void create_worker(void);
 
 
-extern int num_sessions;
 extern volatile int exit_signal;
 extern volatile int shutdown_and_halt;
 extern volatile int running_as_daemon;
index 4f9d1428cf9c9fa84f2690ad829793c9b949bc65..9782d05fc005c5bf9a3f0567cb1c32dd5db65e90 100644 (file)
@@ -38,6 +38,7 @@
 #include "config.h"
 #include "citserver.h"
 #include "sysdep_decls.h"
+#include "context.h"
 
 /*
  * define this to use the new worker_thread method of handling connections
@@ -1196,14 +1197,7 @@ int CtdlThreadSelect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds
         * or timeout so this thread could stop if asked to do so.
         * Anything else means it needs to continue unless the system is shutting down
         */
-       if (ret <= 0)
-       {
-               /**
-                * select says nothing to do so we can change to running if we haven't been asked to stop.
-                */
-               ctdl_thread_internal_change_state(CT, CTDL_THREAD_RUNNING);
-       }
-       else
+       if (ret > 0)
        {
                /**
                 * The select says this thread needs to do something useful.
@@ -1227,6 +1221,8 @@ int CtdlThreadSelect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds
                citthread_mutex_unlock(&CT->ThreadMutex);
        }
 
+       ctdl_thread_internal_change_state(CT, CTDL_THREAD_RUNNING);
+
        return ret;
 }
 
@@ -1347,7 +1343,7 @@ void go_threading(void)
                }
                
                CtdlThreadGC();
-               
+
                if (CtdlThreadGetCount() <= 1) // Shutting down clean up the garbage collector
                {
                        CtdlThreadGC();
@@ -1574,7 +1570,6 @@ int execute_session(struct CitContext *bind_me)
 
 
 
-extern void dead_session_purge(int force);
 
 /*
  * A new worker_thread loop.