Re-Sort Cleanup of event io on shutdown
authorWilfried Goesgens <dothebart@citadel.org>
Sun, 26 Feb 2012 11:27:38 +0000 (12:27 +0100)
committerWilfried Goesgens <dothebart@citadel.org>
Sun, 26 Feb 2012 11:27:38 +0000 (12:27 +0100)
  - create a new CtdlRegisterEVCleanupHook() for cleanup of event based modules on shutdown
  - move cleanup of eventqueue from general cleanup to the very beginning of the shutdown; else terminate_all_sessions() might steal us memory we still need for ordered shutdown.

citadel/citserver.c
citadel/event_client.c
citadel/include/ctdl_module.h
citadel/modules/eventclient/serv_eventclient.c
citadel/modules/pop3client/serv_pop3client.c
citadel/modules/rssclient/serv_rssclient.c
citadel/modules/smtp/serv_smtpeventclient.c
citadel/modules/smtp/serv_smtpqueue.c
citadel/serv_extensions.c
citadel/techdoc/delivery-list.txt
citadel/threads.c

index d989b767ba779a710f2b4a590a857ed1a6d94657..088b584e1107a751cc5b935f4e08c8c858ea5f58 100644 (file)
@@ -222,7 +222,7 @@ void master_cleanup(int exitcode) {
        struct CleanupFunctionHook *fcn;
        static int already_cleaning_up = 0;
 
-       if (already_cleaning_up) while(1) sleep(1);
+       if (already_cleaning_up) while(1) usleep(1000);
        already_cleaning_up = 1;
 
        /* Run any cleanup routines registered by loadable modules */
index 0b6ffabb315f131cb133f7ee0ce2de936d845c58..1589e7303cd4c5c89d981ce56cf42476228e2ce6 100644 (file)
@@ -708,11 +708,11 @@ IO_postdns_callback(struct ev_loop *loop, ev_idle *watcher, int revents)
        AsyncIO *IO = watcher->data;
        EV_syslog(LOG_DEBUG, "event: %s\n", __FUNCTION__);
        become_session(IO->CitContext);
-       assert(IO->DNS.Fail);
        assert(IO->DNS.Query->PostDNS);
        switch (IO->DNS.Query->PostDNS(IO))
        {
        case eAbort:
+               assert(IO->DNS.Fail);
                switch (IO->DNS.Fail(IO)) {
                case eAbort:
 ////                   StopClientWatchers(IO);
index 15a03a521d5ac61793b1f9cfedd9d746643d9e20..9bcdb34a5df49cd004b81c381971756ed5798062 100644 (file)
@@ -104,6 +104,9 @@ void CtdlUnregisterDeleteHook(void (*handler)(char *, long) );
 void CtdlRegisterCleanupHook(void (*fcn_ptr)(void));
 void CtdlUnregisterCleanupHook(void (*fcn_ptr)(void));
 
+void CtdlRegisterEVCleanupHook(void (*fcn_ptr)(void));
+void CtdlUnregisterEVCleanupHook(void (*fcn_ptr)(void));
+
 void CtdlRegisterProtoHook(void (*handler)(char *), char *cmd, char *desc);
 
 void CtdlRegisterServiceHook(int tcp_port,
index eb3f97d1dc84efabfd0cee18485a3bee25e7712c..dd3c4d403bb1fc1c8f66d7b4199d2323e38fcd31 100644 (file)
@@ -622,7 +622,9 @@ void InitEventQueue(void)
        InboundEventQueues[1] = NewHash(1, Flathash);
        InboundEventQueue = InboundEventQueues[0];
 }
+extern void CtdlDestroyEVCleanupHooks(void);
 
+extern int EVQShutDown;
 /*
  * this thread operates the select() etc. via libev.
  */
@@ -659,6 +661,9 @@ void *client_event_thread(void *arg)
        close(event_add_pipe[0]);
        close(event_add_pipe[1]);
 
+       CtdlDestroyEVCleanupHooks();
+
+       EVQShutDown = 1;        
        return(NULL);
 }
 
@@ -805,7 +810,6 @@ CTDL_MODULE_INIT(event_client)
 {
        if (!threading)
        {
-               CtdlRegisterCleanupHook(ShutDownEventQueues);
                InitEventQueue();
                DBInitEventQueue();
                CtdlThreadCreate(client_event_thread);
index 51f1d62db580ef95212d48f6ef46f24a2c376625..0a97df2cc971b402c431c4b6daf5a54dbe9ae3c6 100644 (file)
@@ -1177,7 +1177,7 @@ CTDL_MODULE_INIT(pop3client)
                POP3QueueRooms = NewHash(1, lFlathash);
                POP3FetchUrls = NewHash(1, NULL);
                CtdlRegisterSessionHook(pop3client_scan, EVT_TIMER);
-               CtdlRegisterCleanupHook(pop3_cleanup);
+               CtdlRegisterEVCleanupHook(pop3_cleanup);
        }
 
        /* return our module id for the log */
index 44f779f44be0b56c61b5783e6353271c914cefb9..8a3ba63549a5aadacfa2bfd88d0cc25138541a01 100644 (file)
@@ -547,7 +547,7 @@ CTDL_MODULE_INIT(rssclient)
                RSSFetchUrls = NewHash(1, NULL);
                syslog(LOG_INFO, "%s\n", curl_version());
                CtdlRegisterSessionHook(rssclient_scan, EVT_TIMER);
-               CtdlRegisterCleanupHook(rss_cleanup);
+               CtdlRegisterEVCleanupHook(rss_cleanup);
        }
        return "rssclient";
 }
index 76b8235a90572cff299cb86e2a636a83fd92f5fc..d1815f91bccf3d068ae52172c3edfe48ef1607ea 100644 (file)
@@ -106,7 +106,7 @@ void DeleteSmtpOutMsg(void *v)
        FreeURL(&Msg->Relay);
        FreeStrBuf(&Msg->msgtext);
        FreeAsyncIOContents(&Msg->IO);
-///    memset (Msg, 0, sizeof(SmtpOutMsg)); /* just to be shure... */
+       memset (Msg, 0, sizeof(SmtpOutMsg)); /* just to be shure... */
        free(Msg);
 }
 
index c4b46142a250eef6e7653c256bf0b4d9117ecd9a..e9053981e1e28053bb94240d402f0b0d94074e6d 100644 (file)
@@ -161,17 +161,28 @@ void RemoveQItem(OneQueItem *MyQItem)
 void FreeMailQEntry(void *qv)
 {
        MailQEntry *Q = qv;
+/*
+       syslog(LOG_DEBUG, "---------------%s--------------", __FUNCTION__);
+       cit_backtrace();
+*/
        FreeStrBuf(&Q->Recipient);
        FreeStrBuf(&Q->StatusMessage);
+
+       memset(Q, 0, sizeof(MailQEntry));
        free(Q);
 }
 void FreeQueItem(OneQueItem **Item)
 {
+/*
+       syslog(LOG_DEBUG, "---------------%s--------------", __FUNCTION__);
+       cit_backtrace();
+*/
        DeleteHash(&(*Item)->MailQEntries);
        FreeStrBuf(&(*Item)->EnvelopeFrom);
        FreeStrBuf(&(*Item)->BounceTo);
        FreeStrBuf(&(*Item)->SenderRoom);
        FreeURL(&(*Item)->URL);
+       memset(*Item, 0, sizeof(OneQueItem));
        free(*Item);
        Item = NULL;
 }
@@ -1061,7 +1072,7 @@ CTDL_MODULE_INIT(smtp_queu)
                Put(QItemHandlers, HKEY("submitted"), QItem_Handle_Submitted, reference_free_handler);
                smtp_init_spoolout();
 
-               CtdlRegisterCleanupHook(smtp_evq_cleanup);
+               CtdlRegisterEVCleanupHook(smtp_evq_cleanup);
 
                CtdlRegisterProtoHook(cmd_smtp, "SMTP", "SMTP utility commands");
                CtdlRegisterSessionHook(smtp_do_queue, EVT_TIMER);
index 4f2ddfa1fb38b707b2764a6340fc6834727b0fb7..74eb0c5bda2ab3b117f6ecee6722da8950425195 100644 (file)
@@ -47,6 +47,7 @@
 #endif
 
 struct CleanupFunctionHook *CleanupHookTable = NULL;
+struct CleanupFunctionHook *EVCleanupHookTable = NULL;
 struct SessionFunctionHook *SessionHookTable = NULL;
 struct UserFunctionHook *UserHookTable = NULL;
 struct XmsgFunctionHook *XmsgHookTable = NULL;
@@ -261,6 +262,7 @@ void CtdlUnregisterCleanupHook(void (*fcn_ptr) (void))
        }
 }
 
+
 void CtdlDestroyCleanupHooks(void)
 {
        struct CleanupFunctionHook *cur, *p;
@@ -276,6 +278,56 @@ void CtdlDestroyCleanupHooks(void)
        CleanupHookTable = NULL;
 }
 
+void CtdlRegisterEVCleanupHook(void (*fcn_ptr) (void))
+{
+
+       struct CleanupFunctionHook *newfcn;
+
+       newfcn = (struct CleanupFunctionHook *)
+           malloc(sizeof(struct CleanupFunctionHook));
+       newfcn->next = EVCleanupHookTable;
+       newfcn->h_function_pointer = fcn_ptr;
+       EVCleanupHookTable = newfcn;
+
+       syslog(LOG_INFO, "Registered a new cleanup function\n");
+}
+
+
+void CtdlUnregisterEVCleanupHook(void (*fcn_ptr) (void))
+{
+       struct CleanupFunctionHook *cur, *p;
+
+       for (cur = EVCleanupHookTable; cur != NULL; cur = cur->next) {
+               /* This will also remove duplicates if any */
+               while (cur != NULL &&
+                               fcn_ptr == cur->h_function_pointer) {
+                       syslog(LOG_INFO, "Unregistered cleanup function\n");
+                       p = cur->next;
+                       if (cur == EVCleanupHookTable) {
+                               EVCleanupHookTable = p;
+                       }
+                       free(cur);
+                       cur = p;
+               }
+       }
+}
+
+
+void CtdlDestroyEVCleanupHooks(void)
+{
+       struct CleanupFunctionHook *cur, *p;
+
+       cur = EVCleanupHookTable;
+       while (cur != NULL)
+       {
+               syslog(LOG_INFO, "Destroyed cleanup function\n");
+               p = cur->next;
+               free(cur);
+               cur = p;
+       }
+       EVCleanupHookTable = NULL;
+}
+
 
 void CtdlRegisterSessionHook(void (*fcn_ptr) (void), int EventType)
 {
index da2ba524ec40bc134f50d850fe68b76f5d5f7981..b6663cdb051e4048332b8ec9290a51baebeaa34b 100644 (file)
@@ -93,6 +93,7 @@ fails).
     delivered.  The third parameter may contain any of the following values:
        0 = No delivery has yet been attempted
        2 = Delivery was successful
+       3 = transient error state; like connection failure or DNS lookup failure
        4 = A transient error was experienced ... try again later
        5 = Delivery to this address failed permanently.  The error message
            should be placed in the fourth field so that a bounce message may
index a9fce4eb471282f59e5cbaf1ff5831496e9c3237..062d19911870dc59c20660dfe4b6838c82041924 100644 (file)
@@ -183,7 +183,10 @@ void InitializeMasterTSD(void) {
        memset(&masterTSD, 0, sizeof(struct thread_tsd));
 }
 
+extern void ShutDownEventQueues(void);
 
+int EventQShuttingDown = 0;
+int EVQShutDown = 0;
 /*
  * Initialize the thread system
  */
@@ -211,6 +214,14 @@ void go_threading(void)
        }
 
        /* When we get to this point we are getting ready to shut down our Citadel server */
+       if (!EventQShuttingDown)
+       {
+               EventQShuttingDown = 1;
+               ShutDownEventQueues();
+       }
+       while (!EVQShutDown)
+               usleep(1000);
+
 
        terminate_all_sessions();               /* close all client sockets */
        CtdlShutdownServiceHooks();             /* close all listener sockets to prevent new connections */