]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
DEVEL15-windows-daemon-threads-shutdown-sync-20071223
authorJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 24 Dec 2007 05:24:14 +0000 (05:24 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 24 Dec 2007 05:24:14 +0000 (05:24 +0000)
LICENSE MIT

Windows Error Reporting received crashes caused by a failure to synchronize
the shutdown of the AFS client service with the background daemon threads.
The daemon threads (cm_Daemon, cm_BkgDaemon+, cm_IPAddrDaemon) could be
accessing data structures as they were being freed or unmapped.

Add synchronization mechanisms to signal the termination of the threads
with the shutdown of the service.

(cherry picked from commit 8a923a199d91aae6d1fc9bb6a2f1856fe5dbcb07)

src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/cm_daemon.c
src/WINNT/afsd/cm_daemon.h

index 07299b167e2603726efe8a7903f9c15a379690ab..db29c5cece02d86efd12eac20e8fab6ee9819f44 100644 (file)
@@ -752,9 +752,11 @@ int afsd_InitCM(char **reasonP)
     dummyLen = sizeof(numBkgD);
     code = RegQueryValueEx(parmKey, "Daemons", NULL, NULL,
                             (BYTE *) &numBkgD, &dummyLen);
-    if (code == ERROR_SUCCESS)
+    if (code == ERROR_SUCCESS) {
+        if (numBkgD > CM_MAX_DAEMONS)
+            numBkgD = CM_MAX_DAEMONS;
         afsi_log("%d background daemons", numBkgD);
-    else {
+    else {
         numBkgD = CM_CONFIGDEFAULT_DAEMONS;
         afsi_log("Defaulting to %d background daemons", numBkgD);
     }
index 45cff1c59a4a2d80c1e840aeca7950469e861c9a..bb97c27ee5872dac725a5cda782a1fec5c2a72a7 100644 (file)
@@ -49,33 +49,60 @@ cm_bkgRequest_t *cm_bkgListp;               /* first elt in the list of requests */
 cm_bkgRequest_t *cm_bkgListEndp;       /* last elt in the list of requests */
 
 static int daemon_ShutdownFlag = 0;
+static int cm_nDaemons = 0;
+
+static EVENT_HANDLE cm_Daemon_ShutdownEvent = NULL;
+static EVENT_HANDLE cm_IPAddrDaemon_ShutdownEvent = NULL;
+static EVENT_HANDLE cm_BkgDaemon_ShutdownEvent[CM_MAX_DAEMONS] = 
+       {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 
 #ifndef DJGPP
 void cm_IpAddrDaemon(long parm)
 {
     extern void smb_CheckVCs(void);
+    char * name = "cm_IPAddrDaemon_ShutdownEvent";
+
+    cm_IPAddrDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", name);
 
     rx_StartClientThread();
 
     while (daemon_ShutdownFlag == 0) {
-       DWORD Result = NotifyAddrChange(NULL,NULL);
-       if (Result == NO_ERROR && daemon_ShutdownFlag == 0) {
+       DWORD Result;
+        
+        thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
+        Result = NotifyAddrChange(NULL,NULL);
+        if (Result == NO_ERROR && daemon_ShutdownFlag == 0) {
+            thrd_ResetEvent(cm_IPAddrDaemon_ShutdownEvent);
            Sleep(2500);
-           osi_Log0(afsd_logp, "cm_IpAddrDaemon CheckDownServers");
-            cm_CheckServers(CM_FLAG_CHECKVLDBSERVERS | CM_FLAG_CHECKUPSERVERS | CM_FLAG_CHECKDOWNSERVERS, NULL);
-           cm_ForceNewConnectionsAllServers();
-            cm_CheckServers(CM_FLAG_CHECKFILESERVERS | CM_FLAG_CHECKUPSERVERS | CM_FLAG_CHECKDOWNSERVERS, NULL);
-           smb_CheckVCs();
-            cm_VolStatus_Network_Addr_Change();
+            if (daemon_ShutdownFlag == 0) {
+                osi_Log0(afsd_logp, "cm_IpAddrDaemon CheckDownServers");
+                cm_CheckServers(CM_FLAG_CHECKVLDBSERVERS | CM_FLAG_CHECKUPSERVERS | CM_FLAG_CHECKDOWNSERVERS, NULL);
+                cm_ForceNewConnectionsAllServers();
+                cm_CheckServers(CM_FLAG_CHECKFILESERVERS | CM_FLAG_CHECKUPSERVERS | CM_FLAG_CHECKDOWNSERVERS, NULL);
+                smb_CheckVCs();
+                cm_VolStatus_Network_Addr_Change();
+            }
        }       
     }
+
+    thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
 }
 #endif
 
-void cm_BkgDaemon(long parm)
+void cm_BkgDaemon(void * parm)
 {
     cm_bkgRequest_t *rp;
     afs_int32 code;
+    char name[32] = "";
+    long daemonID = (long)parm;
+
+    snprintf(name, sizeof(name), "cm_BkgDaemon_ShutdownEvent%d", daemonID);
+
+    cm_BkgDaemon_ShutdownEvent[daemonID] = thrd_CreateEvent(NULL, FALSE, FALSE, name);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", name);
 
     rx_StartClientThread();
 
@@ -144,6 +171,9 @@ void cm_BkgDaemon(long parm)
        }
     }
     lock_ReleaseWrite(&cm_daemonLock);
+
+    thrd_SetEvent(cm_BkgDaemon_ShutdownEvent[daemonID]);
+
 }
 
 void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
@@ -322,8 +352,13 @@ void cm_Daemon(long parm)
     unsigned long code;
     struct hostent *thp;
     HMODULE hHookDll;
+    char * name = "cm_Daemon_ShutdownEvent";
     int configureFirewall = IsWindowsFirewallPresent();
 
+    cm_Daemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", name);
+
     if (!configureFirewall) {
        afsi_log("No Windows Firewall detected");
     }
@@ -368,7 +403,7 @@ void cm_Daemon(long parm)
        smb_RestartListeners();
 
         if (daemon_ShutdownFlag == 1)
-            return;
+            break;
 
         if (configureFirewall) {
            /* Open Microsoft Firewall to allow in port 7001 */
@@ -401,7 +436,7 @@ void cm_Daemon(long parm)
            osi_Log0(afsd_logp, "cm_Daemon CheckDownServers");
             cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
             if (daemon_ShutdownFlag == 1)
-                return;
+                break;
            now = osi_Time();
         }
 
@@ -412,7 +447,7 @@ void cm_Daemon(long parm)
            osi_Log0(afsd_logp, "cm_Daemon CheckUpServers");
             cm_CheckServers(CM_FLAG_CHECKUPSERVERS, NULL);
             if (daemon_ShutdownFlag == 1)
-                return;
+                break;
            now = osi_Time();
         }
 
@@ -421,7 +456,7 @@ void cm_Daemon(long parm)
             lastVolCheck = now;
             cm_RefreshVolumes();
             if (daemon_ShutdownFlag == 1)
-                return;
+                break;
            now = osi_Time();
         }
 
@@ -431,7 +466,7 @@ void cm_Daemon(long parm)
             lastVolCBRenewalCheck = now;
             cm_VolumeRenewROCallbacks();
             if (daemon_ShutdownFlag == 1)
-                return;
+                break;
             now = osi_Time();
         }
 
@@ -440,7 +475,7 @@ void cm_Daemon(long parm)
             lastVolCheck = now;
             cm_CheckOfflineVolumes();
             if (daemon_ShutdownFlag == 1)
-                return;
+                break;
            now = osi_Time();
         }
 
@@ -449,7 +484,7 @@ void cm_Daemon(long parm)
             lastCBExpirationCheck = now;
             cm_CheckCBExpiration();
             if (daemon_ShutdownFlag == 1)
-                return;
+                break;
            now = osi_Time();
         }
 
@@ -458,7 +493,7 @@ void cm_Daemon(long parm)
             lastLockCheck = now;
             cm_CheckLocks();
             if (daemon_ShutdownFlag == 1)
-                return;
+                break;
            now = osi_Time();
         }
 
@@ -467,7 +502,7 @@ void cm_Daemon(long parm)
             lastTokenCacheCheck = now;
             cm_CheckTokenCache(now);
             if (daemon_ShutdownFlag == 1)
-                return;
+                break;
            now = osi_Time();
         }
 
@@ -490,15 +525,33 @@ void cm_Daemon(long parm)
             }
         }
 
-        if (daemon_ShutdownFlag == 1)
-            return;
+        if (daemon_ShutdownFlag == 1) {
+            break;
+        }
        thrd_Sleep(30 * 1000);          /* sleep 30 seconds */
     }
+    thrd_SetEvent(cm_Daemon_ShutdownEvent);
 }       
 
 void cm_DaemonShutdown(void)
 {
+    int i;
+    DWORD code;
+
     daemon_ShutdownFlag = 1;
+    osi_Wakeup((LONG_PTR) &cm_bkgListp);
+
+    /* wait for shutdown */
+    if (cm_Daemon_ShutdownEvent)
+        code = thrd_WaitForSingleObject_Event(cm_Daemon_ShutdownEvent, INFINITE); 
+
+    for ( i=0; i<cm_nDaemons; i++) {
+        if (cm_BkgDaemon_ShutdownEvent[i])
+            code = thrd_WaitForSingleObject_Event(cm_BkgDaemon_ShutdownEvent[i], INFINITE);
+    }
+
+    if (cm_IPAddrDaemon_ShutdownEvent)
+        code = thrd_WaitForSingleObject_Event(cm_IPAddrDaemon_ShutdownEvent, INFINITE);
 }
 
 void cm_InitDaemon(int nDaemons)
@@ -507,7 +560,9 @@ void cm_InitDaemon(int nDaemons)
     long pid;
     thread_t phandle;
     int i;
-        
+
+    cm_nDaemons = (nDaemons > CM_MAX_DAEMONS) ? CM_MAX_DAEMONS : nDaemons;
+    
     if (osi_Once(&once)) {
         lock_InitializeRWLock(&cm_daemonLock, "cm_daemonLock");
         osi_EndOnce(&once);
@@ -526,9 +581,9 @@ void cm_InitDaemon(int nDaemons)
         osi_assertx(phandle != NULL, "cm_Daemon thread creation failure");
         thrd_CloseHandle(phandle);
 
-       for(i=0; i < nDaemons; i++) {
+       for(i=0; i < cm_nDaemons; i++) {
             phandle = thrd_Create((SecurityAttrib) 0, 0,
-                                   (ThreadFunc) cm_BkgDaemon, 0, 0, &pid,
+                                   (ThreadFunc) cm_BkgDaemon, (LPVOID)i, 0, &pid,
                                    "cm_BkgDaemon");
             osi_assertx(phandle != NULL, "cm_BkgDaemon thread creation failure");
             thrd_CloseHandle(phandle);
index 8c296e0a99972303747c91b2202e3ff4714d4b30..0c5277577deee854ad4ca135fdb6a6644ead9735 100644 (file)
@@ -41,4 +41,6 @@ typedef struct cm_bkgRequest {
 extern void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, afs_uint32 p1,
        afs_uint32 p2, afs_uint32 p3, afs_uint32 p4, cm_user_t *userp);
 
+#define CM_MAX_DAEMONS 8
+
 #endif /*  __CM_DAEMON_H_ENV_ */