- 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.
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 */
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);
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,
InboundEventQueues[1] = NewHash(1, Flathash);
InboundEventQueue = InboundEventQueues[0];
}
+extern void CtdlDestroyEVCleanupHooks(void);
+extern int EVQShutDown;
/*
* this thread operates the select() etc. via libev.
*/
close(event_add_pipe[0]);
close(event_add_pipe[1]);
+ CtdlDestroyEVCleanupHooks();
+
+ EVQShutDown = 1;
return(NULL);
}
{
if (!threading)
{
- CtdlRegisterCleanupHook(ShutDownEventQueues);
InitEventQueue();
DBInitEventQueue();
CtdlThreadCreate(client_event_thread);
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 */
RSSFetchUrls = NewHash(1, NULL);
syslog(LOG_INFO, "%s\n", curl_version());
CtdlRegisterSessionHook(rssclient_scan, EVT_TIMER);
- CtdlRegisterCleanupHook(rss_cleanup);
+ CtdlRegisterEVCleanupHook(rss_cleanup);
}
return "rssclient";
}
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);
}
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;
}
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);
#endif
struct CleanupFunctionHook *CleanupHookTable = NULL;
+struct CleanupFunctionHook *EVCleanupHookTable = NULL;
struct SessionFunctionHook *SessionHookTable = NULL;
struct UserFunctionHook *UserHookTable = NULL;
struct XmsgFunctionHook *XmsgHookTable = NULL;
}
}
+
void CtdlDestroyCleanupHooks(void)
{
struct CleanupFunctionHook *cur, *p;
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)
{
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
memset(&masterTSD, 0, sizeof(struct thread_tsd));
}
+extern void ShutDownEventQueues(void);
+int EventQShuttingDown = 0;
+int EVQShutDown = 0;
/*
* Initialize the thread system
*/
}
/* 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 */