From d62a8c8ef6806683067f0c25f243b67206f787a1 Mon Sep 17 00:00:00 2001 From: Wilfried Goesgens Date: Fri, 22 Oct 2010 21:08:00 +0200 Subject: [PATCH] * if we're shutting down instantly close our server file descriptions * if we had problems shutting down because of client threads still blocked, close all sessions fd's so they come to an end. --- citadel/context.c | 19 +++++++++++++++++++ citadel/context.h | 3 +++ citadel/include/ctdl_module.h | 1 + citadel/serv_extensions.c | 29 ++++++++++++++++++++++++++++- citadel/threads.c | 9 +++++++-- 5 files changed, 58 insertions(+), 3 deletions(-) diff --git a/citadel/context.c b/citadel/context.c index f6bbf58b6..ef3e7d935 100644 --- a/citadel/context.c +++ b/citadel/context.c @@ -306,6 +306,25 @@ void terminate_idle_sessions(void) CtdlLogPrintf(CTDL_INFO, "Didn't terminate %d protected idle sessions;\n", killed); } +void terminate_stuck_sessions(void) +{ + CitContext *ccptr; + int killed = 0; + + begin_critical_section(S_SESSION_TABLE); + for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) { + if (ccptr->client_socket != -1) + { + close(ccptr->client_socket); + ccptr->client_socket = -1; + killed++; + } + } + end_critical_section(S_SESSION_TABLE); + if (killed > 0) + CtdlLogPrintf(CTDL_INFO, "Flushed %d stuck sessions\n", killed); +} + /* diff --git a/citadel/context.h b/citadel/context.h index 8fc79cfe0..b4607da63 100644 --- a/citadel/context.h +++ b/citadel/context.h @@ -157,6 +157,9 @@ void InitializeMasterCC(void); void dead_session_purge(int force); void set_async_waiting(struct CitContext *ccptr); +/* forcibly close and flush fd's on shutdown */ +void terminate_stuck_sessions(void); + /* Deprecated, user CtdlBumpNewMailCounter() instead */ void BumpNewMailCounter(long) __attribute__ ((deprecated)); diff --git a/citadel/include/ctdl_module.h b/citadel/include/ctdl_module.h index c0a13c89d..067071862 100644 --- a/citadel/include/ctdl_module.h +++ b/citadel/include/ctdl_module.h @@ -86,6 +86,7 @@ void CtdlLogPrintf(enum LogLevel loglevel, const char *format, ...); void CtdlRegisterSessionHook(void (*fcn_ptr)(void), int EventType); void CtdlUnregisterSessionHook(void (*fcn_ptr)(void), int EventType); +void CtdlShutdownServiceHooks(void); void CtdlRegisterUserHook(void (*fcn_ptr)(struct ctdluser *), int EventType); void CtdlUnregisterUserHook(void (*fcn_ptr)(struct ctdluser *), int EventType); diff --git a/citadel/serv_extensions.c b/citadel/serv_extensions.c index 5417d2672..54eaecd53 100644 --- a/citadel/serv_extensions.c +++ b/citadel/serv_extensions.c @@ -781,7 +781,8 @@ void CtdlUnregisterServiceHook(int tcp_port, char *sockpath, { struct ServiceFunctionHook *cur, *p; - for (cur = ServiceHookTable; cur != NULL; cur = cur->next) { + cur = ServiceHookTable; + while (cur != NULL) { /* This will also remove duplicates if any */ while (cur != NULL && !(sockpath && cur->sockpath && @@ -809,6 +810,32 @@ void CtdlUnregisterServiceHook(int tcp_port, char *sockpath, } } + +void CtdlShutdownServiceHooks(void) +{ + /* sort of a duplicate of close_masters() but called earlier */ + struct ServiceFunctionHook *cur; + + cur = ServiceHookTable; + while (cur != NULL) + { + if (cur->msock != -1) + { + close(cur->msock); + cur->msock = -1; + if (cur->sockpath != NULL){ + CtdlLogPrintf(CTDL_INFO, "[%s] Closed UNIX domain socket %s\n", + cur->ServiceName, + cur->sockpath); + } else { + CtdlLogPrintf(CTDL_INFO, "[%s] closing service\n", + cur->ServiceName); + } + } + cur = cur->next; + } +} + void CtdlDestroyServiceHook(void) { struct ServiceFunctionHook *cur, *p; diff --git a/citadel/threads.c b/citadel/threads.c index ec64ceaef..1afad1cfc 100644 --- a/citadel/threads.c +++ b/citadel/threads.c @@ -352,7 +352,9 @@ void CtdlThreadStopAll(void) { /* First run any registered shutdown hooks. This probably doesn't belong here. */ PerformSessionHooks(EVT_SHUTDOWN); - + + /* then close all tcp ports so nobody else can talk to us anymore. */ + CtdlShutdownServiceHooks(); //FIXME: The signalling of the condition should not be in the critical_section // We need to build a list of threads we are going to signal and then signal them afterwards @@ -712,7 +714,10 @@ void CtdlThreadGC (void) if ((that_thread->state == CTDL_THREAD_STOP_REQ || that_thread->state == CTDL_THREAD_STOPPING) && (!citthread_equal(that_thread->tid, citthread_self()))) - CtdlLogPrintf(CTDL_DEBUG, "Waiting for thread %s (0x%08lx) to exit.\n", that_thread->name, that_thread->tid); + { + CtdlLogPrintf(CTDL_DEBUG, "Waiting for thread %s (0x%08lx) to exit.\n", that_thread->name, that_thread->tid); + terminate_stuck_sessions(); + } else { /** -- 2.30.2