X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fcontext.c;h=953d1d6ae77b6e1c8dd1409f3eeae5bd9b985d2d;hb=aa7365c86de8e26e796d3aa3fd605c85d8c26220;hp=70657537ec02e20248dfb7467b4f1005d67fa037;hpb=cdb76f6e9aafb137b3969f96ad1731e19e534fe0;p=citadel.git diff --git a/citadel/context.c b/citadel/context.c index 70657537e..953d1d6ae 100644 --- a/citadel/context.c +++ b/citadel/context.c @@ -2,21 +2,15 @@ * Citadel context management stuff. * Here's where we (hopefully) have all the code that manipulates contexts. * - * Copyright (c) 1987-2010 by the citadel.org team + * Copyright (c) 1987-2011 by the citadel.org team * * This program is open source software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. + * it under the terms of the GNU General Public License, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "sysdep.h" @@ -84,9 +78,9 @@ #include "user_ops.h" #include "control.h" +int DebugSession = 0; - -citthread_key_t MyConKey; /* TSD key for MyContext() */ +pthread_key_t MyConKey; /* TSD key for MyContext() */ CitContext masterCC; @@ -159,7 +153,7 @@ int CtdlTerminateOtherSession (int session_num) return TERM_NOTALLOWED; } - syslog(LOG_DEBUG, "Locating session to kill\n"); + CONM_syslog(LOG_DEBUG, "Locating session to kill\n"); begin_critical_section(S_SESSION_TABLE); for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) { if (session_num == ccptr->cs_pid) { @@ -259,12 +253,8 @@ int CtdlIsUserLoggedInByNum (long usernum) * This function is used *VERY* frequently and must be kept small. */ CitContext *MyContext(void) { - register CitContext *c; - - return ((c = (CitContext *) citthread_getspecific(MyConKey), - c == NULL) ? &masterCC : c - ); + return ((c = (CitContext *) pthread_getspecific(MyConKey), c == NULL) ? &masterCC : c); } @@ -280,33 +270,38 @@ void terminate_idle_sessions(void) { CitContext *ccptr; time_t now; - int session_to_kill; int killed = 0; int longrunners = 0; now = time(NULL); - session_to_kill = 0; begin_critical_section(S_SESSION_TABLE); for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) { - if ( (ccptr!=CC) - && (config.c_sleeping > 0) - && (now - (ccptr->lastcmd) > config.c_sleeping) ) { + if ( + (ccptr != CC) + && (config.c_sleeping > 0) + && (now - (ccptr->lastcmd) > config.c_sleeping) + ) { if (!ccptr->dont_term) { ccptr->kill_me = KILLME_IDLE; ++killed; } - else - longrunners ++; + else { + ++longrunners; + } } } end_critical_section(S_SESSION_TABLE); if (killed > 0) - syslog(LOG_INFO, "Scheduled %d idle sessions for termination\n", killed); + CON_syslog(LOG_INFO, "Scheduled %d idle sessions for termination\n", killed); if (longrunners > 0) - syslog(LOG_INFO, "Didn't terminate %d protected idle sessions;\n", killed); + CON_syslog(LOG_INFO, "Didn't terminate %d protected idle sessions", longrunners); } -void terminate_stuck_sessions(void) + +/* + * During shutdown, close the sockets of any sessions still connected. + */ +void terminate_all_sessions(void) { CitContext *ccptr; int killed = 0; @@ -315,14 +310,16 @@ void terminate_stuck_sessions(void) for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) { if (ccptr->client_socket != -1) { + CON_syslog(LOG_INFO, "terminate_all_sessions() is murdering %s", ccptr->curr_user); close(ccptr->client_socket); ccptr->client_socket = -1; killed++; } } end_critical_section(S_SESSION_TABLE); - if (killed > 0) - syslog(LOG_INFO, "Flushed %d stuck sessions\n", killed); + if (killed > 0) { + CON_syslog(LOG_INFO, "Flushed %d stuck sessions\n", killed); + } } @@ -333,15 +330,16 @@ void terminate_stuck_sessions(void) void RemoveContext (CitContext *con) { const char *c; - if (con==NULL) { - syslog(LOG_ERR, "WARNING: RemoveContext() called with NULL!\n"); + if (con == NULL) { + CONM_syslog(LOG_ERR, "WARNING: RemoveContext() called with NULL!"); return; } c = con->ServiceName; - if (c == NULL) + if (c == NULL) { c = "WTF?"; - syslog(LOG_DEBUG, "RemoveContext(%s) session %d\n", c, con->cs_pid); - cit_backtrace (); + } + CON_syslog(LOG_DEBUG, "RemoveContext(%s) session %d", c, con->cs_pid); +/// cit_backtrace(); /* Run any cleanup routines registered by loadable modules. * Note: We have to "become_session()" because the cleanup functions @@ -350,18 +348,19 @@ void RemoveContext (CitContext *con) become_session(con); CtdlUserLogout(); PerformSessionHooks(EVT_STOP); + client_close(); /* If the client is still connected, blow 'em away. */ become_session(NULL); - syslog(LOG_NOTICE, "[%3d] Session ended.\n", con->cs_pid); + CON_syslog(LOG_NOTICE, "[%3d]SRV[%s] Session ended.", con->cs_pid, c); /* * If the client is still connected, blow 'em away. - * if the socket is 0, its already gone or was never there. + * if the socket is 0 or -1, its already gone or was never there. */ - if (con->client_socket != 0) + if (con->client_socket > 0) { - syslog(LOG_DEBUG, "Closing socket %d\n", con->client_socket); - if (close(con->client_socket)) syslog(LOG_NOTICE, "close() : %s", strerror(errno)); + CON_syslog(LOG_NOTICE, "Closing socket %d", con->client_socket); + close(con->client_socket); } /* If using AUTHMODE_LDAP, free the DN */ @@ -369,19 +368,18 @@ void RemoveContext (CitContext *con) free(con->ldap_dn); con->ldap_dn = NULL; } - + FreeStrBuf(&con->StatusMessage); FreeStrBuf(&con->MigrateBuf); FreeStrBuf(&con->RecvBuf.Buf); if (con->cached_msglist) { free(con->cached_msglist); } - syslog(LOG_DEBUG, "Done with RemoveContext()\n"); + CONM_syslog(LOG_DEBUG, "Done with RemoveContext()"); } - /* * 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 @@ -394,11 +392,12 @@ CitContext *CreateNewContext(void) { me = (CitContext *) malloc(sizeof(CitContext)); if (me == NULL) { - syslog(LOG_ALERT, "citserver: can't allocate memory!!\n"); + CONM_syslog(LOG_ALERT, "citserver: can't allocate memory!!\n"); return NULL; } memset(me, 0, sizeof(CitContext)); - /* Give the contaxt a name. Hopefully makes it easier to track */ + + /* Give the context 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 @@ -411,12 +410,16 @@ CitContext *CreateNewContext(void) { * the list. */ me->MigrateBuf = NewStrBuf(); + me->RecvBuf.Buf = NewStrBuf(); + + me->lastcmd = time(NULL); /* set lastcmd to now to prevent idle timer infanticide TODO: if we have a valid IO, use that to set the timer. */ + + begin_critical_section(S_SESSION_TABLE); me->cs_pid = ++next_pid; me->prev = NULL; me->next = ContextList; - me->lastcmd = time(NULL); /* set lastcmd to now to prevent idle timer infanticide */ ContextList = me; if (me->next != NULL) { me->next->prev = me; @@ -439,7 +442,7 @@ CitContext *CloneContext(CitContext *CloneMe) { me = (CitContext *) malloc(sizeof(CitContext)); if (me == NULL) { - syslog(LOG_ALERT, "citserver: can't allocate memory!!\n"); + CONM_syslog(LOG_ALERT, "citserver: can't allocate memory!!\n"); return NULL; } memcpy(me, CloneMe, sizeof(CitContext)); @@ -543,23 +546,13 @@ void CtdlFillSystemContext(CitContext *context, char *name) if (context->user.usernum == 0) { /* old system user with number 0, upgrade it */ context->user.usernum = get_new_user_number(); - syslog(LOG_DEBUG, "Upgrading system user \"%s\" from user number 0 to user number %ld\n", context->user.fullname, context->user.usernum); + CON_syslog(LOG_INFO, "Upgrading system user \"%s\" from user number 0 to user number %ld\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); } } -/* - * flush it again... - */ -void CtdlClearSystemContext(void) -{ - CitContext *CCC = MyContext(); - - memset(CCC, 0, sizeof(CitContext)); - citthread_setspecific(MyConKey, NULL); -} /* * Cleanup any contexts that are left lying around @@ -587,7 +580,7 @@ void context_cleanup(void) rem = ptr->next; --num_sessions; - syslog(LOG_DEBUG, "context_cleanup(): Purging session #%d %s\n", ptr->cs_pid, ptr->ServiceName); + CON_syslog(LOG_DEBUG, "context_cleanup(): purging session %d\n", ptr->cs_pid); RemoveContext(ptr); free (ptr); ptr = rem; @@ -647,7 +640,7 @@ void dead_session_purge(int force) { * is allocated privately on this thread's stack. */ while (rem != NULL) { - syslog(LOG_DEBUG, "dead_session_purge(): purging session %d, reason=%d\n", rem->cs_pid, rem->kill_me); + CON_syslog(LOG_DEBUG, "dead_session_purge(): purging session %d, reason=%d\n", rem->cs_pid, rem->kill_me); RemoveContext(rem); ptr = rem; rem = rem->next; @@ -664,7 +657,7 @@ void dead_session_purge(int force) { * function initializes it. */ void InitializeMasterCC(void) { - memset(&masterCC, 0, sizeof( CitContext)); + memset(&masterCC, 0, sizeof(struct CitContext)); masterCC.internal_pgm = 1; masterCC.cs_pid = 0; } @@ -678,7 +671,7 @@ void InitializeMasterCC(void) { */ void set_async_waiting(struct CitContext *ccptr) { - syslog(LOG_DEBUG, "Setting async_waiting flag for session %d\n", ccptr->cs_pid); + CON_syslog(LOG_DEBUG, "Setting async_waiting flag for session %d\n", ccptr->cs_pid); if (ccptr->is_async) { ccptr->async_waiting++; if (ccptr->state == CON_IDLE) { @@ -686,3 +679,16 @@ void set_async_waiting(struct CitContext *ccptr) } } } + + +void DebugSessionEnable(const int n) +{ + DebugSession = n; +} +CTDL_MODULE_INIT(session) +{ + if (!threading) { + CtdlRegisterDebugFlagHook(HKEY("session"), DebugSessionEnable, &DebugSession); + } + return "session"; +}