* if we're shutting down instantly close our server file descriptions
authorWilfried Goesgens <dothebart@citadel.org>
Fri, 22 Oct 2010 19:08:00 +0000 (21:08 +0200)
committerWilfried Goesgens <dothebart@citadel.org>
Fri, 22 Oct 2010 19:08:00 +0000 (21:08 +0200)
* 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
citadel/context.h
citadel/include/ctdl_module.h
citadel/serv_extensions.c
citadel/threads.c

index f6bbf58b635d95fdd1b6fd6b7aae348adfaebdcf..ef3e7d935d7fd8d43e648b6fea9818a3c84e134d 100644 (file)
@@ -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);
+}
+
 
 
 /*
index 8fc79cfe0d4bb64354d266c6da60e872f0eec7a4..b4607da63dc8ca37ab65b512b867722ce83c19b6 100644 (file)
@@ -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));
 
index c0a13c89d5d5a72c43f8bbd8505a325542745647..067071862122cef7d231c80f46749585caa7693f 100644 (file)
@@ -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);
index 5417d2672ed65de4b7833cccbe1514a1de823c5e..54eaecd536a4233921a9ca72cefd15ad9b0be69f 100644 (file)
@@ -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;
index ec64ceaefb4407b345ed5858cb010e4f15a093ae..1afad1cfcac72aa64d8a699c58cf070b821d1b42 100644 (file)
@@ -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
                {
                        /**