From cdc34fa661ed54fdcebf86521496220cc28f4943 Mon Sep 17 00:00:00 2001 From: Wilfried Goesgens Date: Sun, 26 Feb 2012 12:27:38 +0100 Subject: [PATCH] Re-Sort Cleanup of event io on shutdown - 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 | 2 +- citadel/event_client.c | 2 +- citadel/include/ctdl_module.h | 3 ++ .../modules/eventclient/serv_eventclient.c | 6 ++- citadel/modules/pop3client/serv_pop3client.c | 2 +- citadel/modules/rssclient/serv_rssclient.c | 2 +- citadel/modules/smtp/serv_smtpeventclient.c | 2 +- citadel/modules/smtp/serv_smtpqueue.c | 13 ++++- citadel/serv_extensions.c | 52 +++++++++++++++++++ citadel/techdoc/delivery-list.txt | 1 + citadel/threads.c | 11 ++++ 11 files changed, 89 insertions(+), 7 deletions(-) diff --git a/citadel/citserver.c b/citadel/citserver.c index d989b767b..088b584e1 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -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 */ diff --git a/citadel/event_client.c b/citadel/event_client.c index 0b6ffabb3..1589e7303 100644 --- a/citadel/event_client.c +++ b/citadel/event_client.c @@ -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); diff --git a/citadel/include/ctdl_module.h b/citadel/include/ctdl_module.h index 15a03a521..9bcdb34a5 100644 --- a/citadel/include/ctdl_module.h +++ b/citadel/include/ctdl_module.h @@ -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, diff --git a/citadel/modules/eventclient/serv_eventclient.c b/citadel/modules/eventclient/serv_eventclient.c index eb3f97d1d..dd3c4d403 100644 --- a/citadel/modules/eventclient/serv_eventclient.c +++ b/citadel/modules/eventclient/serv_eventclient.c @@ -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); diff --git a/citadel/modules/pop3client/serv_pop3client.c b/citadel/modules/pop3client/serv_pop3client.c index 51f1d62db..0a97df2cc 100644 --- a/citadel/modules/pop3client/serv_pop3client.c +++ b/citadel/modules/pop3client/serv_pop3client.c @@ -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 */ diff --git a/citadel/modules/rssclient/serv_rssclient.c b/citadel/modules/rssclient/serv_rssclient.c index 44f779f44..8a3ba6354 100644 --- a/citadel/modules/rssclient/serv_rssclient.c +++ b/citadel/modules/rssclient/serv_rssclient.c @@ -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"; } diff --git a/citadel/modules/smtp/serv_smtpeventclient.c b/citadel/modules/smtp/serv_smtpeventclient.c index 76b8235a9..d1815f91b 100644 --- a/citadel/modules/smtp/serv_smtpeventclient.c +++ b/citadel/modules/smtp/serv_smtpeventclient.c @@ -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); } diff --git a/citadel/modules/smtp/serv_smtpqueue.c b/citadel/modules/smtp/serv_smtpqueue.c index c4b46142a..e9053981e 100644 --- a/citadel/modules/smtp/serv_smtpqueue.c +++ b/citadel/modules/smtp/serv_smtpqueue.c @@ -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); diff --git a/citadel/serv_extensions.c b/citadel/serv_extensions.c index 4f2ddfa1f..74eb0c5bd 100644 --- a/citadel/serv_extensions.c +++ b/citadel/serv_extensions.c @@ -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) { diff --git a/citadel/techdoc/delivery-list.txt b/citadel/techdoc/delivery-list.txt index da2ba524e..b6663cdb0 100644 --- a/citadel/techdoc/delivery-list.txt +++ b/citadel/techdoc/delivery-list.txt @@ -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 diff --git a/citadel/threads.c b/citadel/threads.c index a9fce4eb4..062d19911 100644 --- a/citadel/threads.c +++ b/citadel/threads.c @@ -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 */ -- 2.30.2