cmd_TERM: also kill AsyncIO contexts
authorWilfried Goesgens <dothebart@citadel.org>
Mon, 23 Jul 2012 14:26:35 +0000 (16:26 +0200)
committerWilfried Goesgens <dothebart@citadel.org>
Mon, 23 Jul 2012 14:26:35 +0000 (16:26 +0200)
  - the next_pid var has to be global, so we have a uniq source of session numbers.
  - during cloning sessions, cached_msglist and CIT_ICAL mustn't be copied.
  - FreeAsyncIOContents(): NULL pointer to context after flagging it for deletion.
  - InitIOStruct() / InitcURLIOStruct(): IO and CC are now doublepointered, know each others.
  - KillAsyncIOContext () detect in which event-queue the context is running
  - Join that queue, and call the terminator hook of the other session.
  - self-terminate afterwards.

citadel/context.c
citadel/context.h
citadel/event_client.c
citadel/event_client.h

index 953d1d6ae77b6e1c8dd1409f3eeae5bd9b985d2d..255458d506d4e22376f074d181b01fbb41c4e68b 100644 (file)
@@ -88,6 +88,7 @@ CitContext *ContextList = NULL;
 
 time_t last_purge = 0;                         /* Last dead session purge */
 int num_sessions = 0;                          /* Current number of sessions */
+int next_pid = 0;
 
 /* Flag for single user mode */
 static int want_single_user = 0;
@@ -146,26 +147,46 @@ int CtdlIsSingleUser(void)
  */
 int CtdlTerminateOtherSession (int session_num)
 {
+       struct CitContext *CCC = CC;
        int ret = 0;
        CitContext *ccptr;
+       int aide;
 
-       if (session_num == CC->cs_pid) {
-               return TERM_NOTALLOWED;
-       }
+       if (session_num == CCC->cs_pid) return TERM_NOTALLOWED;
+
+       aide = ( (CCC->user.axlevel >= AxAideU) || (CCC->internal_pgm) ) ;
 
        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) {
                        ret |= TERM_FOUND;
-                       if ((ccptr->user.usernum == CC->user.usernum)
-                          || (CC->user.axlevel >= AxAideU)) {
+                       if ((ccptr->user.usernum == CCC->user.usernum) || aide) {
                                ret |= TERM_ALLOWED;
-                               ccptr->kill_me = KILLME_ADMIN_TERMINATE;
                        }
+                       break;
                }
        }
-       end_critical_section(S_SESSION_TABLE);
+
+       if (((ret & TERM_FOUND) != 0) && ((ret & TERM_ALLOWED) == 0))
+       {
+               if (ccptr->IO != NULL) {
+                       AsyncIO *IO = ccptr->IO;
+                       end_critical_section(S_SESSION_TABLE);
+                       KillAsyncIOContext(IO);
+               }
+               else
+               {
+                       if (ccptr->user.usernum == CCC->user.usernum)
+                               ccptr->kill_me = KILLME_ADMIN_TERMINATE;
+                       else
+                               ccptr->kill_me = KILLME_IDLE;
+                       end_critical_section(S_SESSION_TABLE);
+               }
+       }
+       else
+               end_critical_section(S_SESSION_TABLE);
+
        return ret;
 }
 
@@ -388,7 +409,6 @@ void RemoveContext (CitContext *con)
  */
 CitContext *CreateNewContext(void) {
        CitContext *me;
-       static int next_pid = 0;
 
        me = (CitContext *) malloc(sizeof(CitContext));
        if (me == NULL) {
@@ -438,7 +458,6 @@ CitContext *CreateNewContext(void) {
  */
 CitContext *CloneContext(CitContext *CloneMe) {
        CitContext *me;
-       static int next_pid = 0;
 
        me = (CitContext *) malloc(sizeof(CitContext));
        if (me == NULL) {
@@ -464,7 +483,10 @@ CitContext *CloneContext(CitContext *CloneMe) {
        me->openid_data = NULL;
        me->ldap_dn = NULL;
        me->session_specific_data = NULL;
+       
+       me->CIT_ICAL = NULL;
 
+       me->cached_msglist = NULL;
        me->download_fp = NULL;
        me->upload_fp = NULL;
        me->client_socket = 0;
index 903195c37ccbee9f3a7f400ff885b3dcf9b5062b..9243d5148230270912919694e908ee9b68a81dea 100644 (file)
@@ -28,6 +28,8 @@ typedef enum __CCState {
        CON_SYS                 /* This is a system context and mustn't be purged */
 } CCState;
 
+typedef struct AsyncIO AsyncIO; /* forward declaration for event_client.h */
+typedef struct CitContext CitContext;
 
 /*
  * Here's the big one... the Citadel context structure.
@@ -37,8 +39,8 @@ typedef enum __CCState {
  *
  */
 struct CitContext {
-       struct CitContext *prev;        /* Link to previous session in list */
-       struct CitContext *next;        /* Link to next session in the list */
+       CitContext *prev;       /* Link to previous session in list */
+       CitContext *next;       /* Link to next session in the list */
 
        int cs_pid;             /* session ID */
        int dont_term;          /* for special activities like artv so we don't get killed */
@@ -140,9 +142,10 @@ struct CitContext {
 
        long *cached_msglist;                   /* results of the previous CtdlForEachMessage() */
        int cached_num_msgs;
+
+       AsyncIO *IO;                            /* if this session has AsyncIO going on... */
 };
 
-typedef struct CitContext CitContext;
 
 
 #define CC MyContext()
index 35581e516b37022ef18b602117fb0c63d60e3acd..eb8a682fcbad3c8586bad0d188e3193ac1331ab0 100644 (file)
@@ -298,6 +298,7 @@ void FreeAsyncIOContents(AsyncIO *IO)
        if (Ctx) {
                Ctx->state = CON_IDLE;
                Ctx->kill_me = 1;
+               IO->CitContext = NULL;
        }
 }
 
@@ -1031,7 +1032,8 @@ void InitIOStruct(AsyncIO *IO,
        IO->Data          = Data;
 
        IO->CitContext    = CloneContext(CC);
-       ((CitContext *)IO->CitContext)->session_specific_data = (char*) Data;
+       IO->CitContext->session_specific_data = (char*) Data;
+       IO->CitContext->IO = IO;
 
        IO->NextState     = NextState;
 
@@ -1068,7 +1070,8 @@ int InitcURLIOStruct(AsyncIO *IO,
        IO->Data          = Data;
 
        IO->CitContext    = CloneContext(CC);
-       ((CitContext *)IO->CitContext)->session_specific_data = (char*) Data;
+       IO->CitContext->session_specific_data = (char*) Data;
+       IO->CitContext->IO = IO;
 
        IO->SendDone      = SendDone;
        IO->Terminate     = Terminate;
@@ -1082,6 +1085,85 @@ int InitcURLIOStruct(AsyncIO *IO,
 
 }
 
+
+typedef struct KillOtherSessionContext {
+       AsyncIO IO;
+       AsyncIO *OtherOne;
+}KillOtherSessionContext;
+
+eNextState KillTerminate(AsyncIO *IO)
+{
+       KillOtherSessionContext *Ctx = (KillOtherSessionContext*)IO->Data;
+       EV_syslog(LOG_DEBUG, "%s Exit\n", __FUNCTION__);
+       FreeAsyncIOContents(IO);
+       memset(Ctx, 0, sizeof(KillOtherSessionContext));
+       free(Ctx);
+       return eAbort;
+
+}
+
+eNextState KillShutdown(AsyncIO *IO)
+{
+       return eTerminateConnection;
+}
+
+eNextState KillOtherContextNow(AsyncIO *IO)
+{
+       KillOtherSessionContext *Ctx = IO->Data;
+
+       if (Ctx->OtherOne->ShutdownAbort != NULL)
+               Ctx->OtherOne->ShutdownAbort(Ctx->OtherOne);
+       return eTerminateConnection;
+}
+
+void KillAsyncIOContext(AsyncIO *IO)
+{
+       KillOtherSessionContext *Ctx;
+
+       Ctx = (KillOtherSessionContext*) malloc(sizeof(KillOtherSessionContext));
+       memset(Ctx, 0, sizeof(KillOtherSessionContext));
+       
+       InitIOStruct(&Ctx->IO,
+                    Ctx,
+                    eReadMessage,
+                    NULL,
+                    NULL,
+                    NULL,
+                    NULL,
+                    KillTerminate,
+                    NULL,
+                    NULL,
+                    NULL,
+                    KillShutdown);
+
+       Ctx->OtherOne = IO;
+
+       switch(IO->NextState) {
+       case eSendDNSQuery:
+       case eReadDNSReply:
+
+       case eConnect:
+       case eSendReply:
+       case eSendMore:
+       case eSendFile:
+
+       case eReadMessage:
+       case eReadMore:
+       case eReadPayload:
+       case eReadFile:
+               QueueEventContext(&Ctx->IO, KillOtherContextNow);
+               break;
+       case eDBQuery:
+               QueueDBOperation(&Ctx->IO, KillOtherContextNow);
+               break;
+       case eTerminateConnection:
+       case eAbort:
+               /*hm, its already dying, dunno which Queue its in... */
+               free(Ctx);
+       }
+       
+}
+
 extern int DebugEventLoopBacktrace;
 void EV_backtrace(AsyncIO *IO)
 {
index 9c13039914c6338c49512a456629913828333470..2d26c2877b645030a5df06af25979db49f1199b4 100644 (file)
@@ -24,6 +24,7 @@
 #include <curl/curl.h>
 
 typedef struct AsyncIO AsyncIO;
+typedef struct CitContext CitContext;
 
 typedef enum _eNextState {
        eSendDNSQuery,
@@ -164,7 +165,7 @@ struct AsyncIO {
 
        /* Context specific data; Hint: put AsyncIO in there */
        void *Data;        /* application specific data */
-       void *CitContext;  /* Citadel Session context... */
+       CitContext *CitContext;  /* Citadel Session context... */
 };
 
 typedef struct _IOAddHandler {
@@ -296,7 +297,7 @@ int InitcURLIOStruct(AsyncIO *IO,
                     IO_CallBack Terminate,
                     IO_CallBack DBTerminate,
                     IO_CallBack ShutdownAbort);
-
+void KillAsyncIOContext(AsyncIO *IO);
 void StopCurlWatchers(AsyncIO *IO);