/*
- * Terminate a session and remove its context data structure.
+ * Terminate a session.
*/
void RemoveContext (struct CitContext *con)
{
if (con==NULL) {
- lprintf(CTDL_ERR, "WARNING: RemoveContext() called with NULL!\n");
+ lprintf(CTDL_ERR,
+ "WARNING: RemoveContext() called with NULL!\n");
return;
}
- lprintf(CTDL_DEBUG, "RemoveContext() called\n");
-
- /* Remove the context from the global context list. This needs
- * to get done FIRST to avoid concurrency problems. It is *vitally*
- * important to keep num_sessions accurate!!
- */
- lprintf(CTDL_DEBUG, "Removing context for session %d\n", con->cs_pid);
- begin_critical_section(S_SESSION_TABLE);
- if (con->prev) {
- con->prev->next = con->next;
- }
- else {
- ContextList = con->next;
- }
- if (con->next) {
- con->next->prev = con->prev;
- }
- --num_sessions;
- end_critical_section(S_SESSION_TABLE);
+ lprintf(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
lprintf(CTDL_DEBUG, "Closing socket %d\n", con->client_socket);
close(con->client_socket);
- /* This is where we used to check for scheduled shutdowns. */
-
- /* Free up the memory used by this context */
- free(con);
-
lprintf(CTDL_DEBUG, "Done with RemoveContext()\n");
}
if (!strncmp(argv[a], "-l", 2)) {
safestrncpy(facility, argv[a], sizeof(facility));
syslog_facility = SyslogFacility(facility);
+ enable_syslog = 1;
}
/* run in the background if -d was specified */
}
/* daemonize, if we were asked to */
- if (running_as_daemon) { start_daemon(0); drop_root_perms = 1; }
+ if (running_as_daemon) {
+ start_daemon(0);
+ drop_root_perms = 1;
+ }
/* initialize the syslog facility */
- if (running_as_daemon) openlog("Citadel", LOG_NDELAY, syslog_facility);
- else openlog("Citadel", LOG_PERROR|LOG_NDELAY, syslog_facility);
- setlogmask(LOG_UPTO(verbosity));
+ if (enable_syslog) {
+ if (running_as_daemon) {
+ openlog("citadel", LOG_NDELAY, syslog_facility);
+ }
+ else {
+ openlog("citadel", LOG_PERROR|LOG_NDELAY,
+ syslog_facility);
+ }
+ setlogmask(LOG_UPTO(verbosity));
+ }
/* Tell 'em who's in da house */
lprintf(CTDL_NOTICE, "\n");
int num_sessions = 0; /* Current number of sessions */
int syslog_facility = (-1);
-
+int enable_syslog = 0;
+extern int running_as_daemon;
/*
* lprintf() ... Write logging information
*/
-extern int running_as_daemon;
-static int enable_syslog = 1;
void lprintf(enum LogLevel loglevel, const char *format, ...) {
va_list arg_ptr;
* session to which the calling thread is currently bound.
*/
if (pthread_key_create(&MyConKey, NULL) != 0) {
- lprintf(CTDL_CRIT, "Can't create TSD key!! %s\n", strerror(errno));
+ lprintf(CTDL_CRIT, "Can't create TSD key: %s\n",
+ strerror(errno));
}
/*
/* set to nonblock - we need this for some obscure situations */
if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) {
- lprintf(CTDL_EMERG, "citserver: Can't set socket to non-blocking: %s\n",
+ lprintf(CTDL_EMERG,
+ "citserver: Can't set socket to non-blocking: %s\n",
strerror(errno));
close(s);
return(-1);
}
if (listen(s, actual_queue_len) < 0) {
- lprintf(CTDL_EMERG, "citserver: Can't listen: %s\n", strerror(errno));
+ lprintf(CTDL_EMERG, "citserver: Can't listen: %s\n",
+ strerror(errno));
close(s);
return(-1);
}
/* set to nonblock - we need this for some obscure situations */
if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) {
- lprintf(CTDL_EMERG, "citserver: Can't set socket to non-blocking: %s\n",
+ lprintf(CTDL_EMERG,
+ "citserver: Can't set socket to non-blocking: %s\n",
strerror(errno));
close(s);
return(-1);
}
if (listen(s, actual_queue_len) < 0) {
- lprintf(CTDL_EMERG, "citserver: Can't listen: %s\n", strerror(errno));
+ lprintf(CTDL_EMERG, "citserver: Can't listen: %s\n",
+ strerror(errno));
return(-1);
}
*/
me->state = CON_EXECUTING;
-
/*
* Generate a unique session number and insert this context into
* the list.
* if such an action is appropriate.
*/
void dead_session_purge(int force) {
- struct CitContext *ptr, *rem;
+ struct CitContext *ptr; /* general-purpose utility pointer */
+ struct CitContext *rem = NULL; /* list of sessions to be destroyed */
if (force == 0) {
if ( (time(NULL) - last_purge) < 5 ) {
}
time(&last_purge);
- do {
- rem = NULL;
- begin_critical_section(S_SESSION_TABLE);
- for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
- if ( (ptr->state == CON_IDLE) && (ptr->kill_me) ) {
- rem = ptr;
+ begin_critical_section(S_SESSION_TABLE);
+ for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
+ if ( (ptr->state == CON_IDLE) && (ptr->kill_me) ) {
+
+ /* Remove the session from the active list */
+ if (ptr->prev) {
+ ptr->prev->next = ptr->next;
}
- }
- end_critical_section(S_SESSION_TABLE);
+ else {
+ ContextList = ptr->next;
+ }
+ if (ptr->next) {
+ ptr->next->prev = ptr->prev;
+ }
+
+ --num_sessions;
+
+ /* And put it on our to-be-destroyed list */
+ ptr->next = rem;
+ rem = ptr;
- /* RemoveContext() enters its own S_SESSION_TABLE critical
- * section, so we have to do it like this.
- */
- if (rem != NULL) {
- lprintf(CTDL_DEBUG, "Purging session %d\n", rem->cs_pid);
- RemoveContext(rem);
}
+ }
+ end_critical_section(S_SESSION_TABLE);
- } while (rem != NULL);
+ /* 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) {
+ lprintf(CTDL_DEBUG, "Purging session %d\n", rem->cs_pid);
+ RemoveContext(rem);
+ ptr = rem;
+ rem = rem->next;
+ free(ptr);
+ }
/* Raise the size of the worker thread pool if necessary. */
-
if ( (num_sessions > num_threads)
&& (num_threads < config.c_max_workers) ) {
begin_critical_section(S_WORKER_LIST);