Author: mturk
Date: Mon Mar 15 07:41:49 2010
New Revision: 923104

URL: http://svn.apache.org/viewvc?rev=923104&view=rev
Log:
Fix DAEMON-108 by stopping dependent service first

Modified:
    commons/proper/daemon/trunk/RELEASE-NOTES.txt
    commons/proper/daemon/trunk/src/native/nt/procrun/src/service.c

Modified: commons/proper/daemon/trunk/RELEASE-NOTES.txt
URL: 
http://svn.apache.org/viewvc/commons/proper/daemon/trunk/RELEASE-NOTES.txt?rev=923104&r1=923103&r2=923104&view=diff
==============================================================================
--- commons/proper/daemon/trunk/RELEASE-NOTES.txt (original)
+++ commons/proper/daemon/trunk/RELEASE-NOTES.txt Mon Mar 15 07:41:49 2010
@@ -35,7 +35,7 @@ NEW FEATURES:
 
 BUG FIXES:
 
-1.0.3: DAEMON-139
+1.0.3: DAEMON-108, DAEMON-139
 
 1.0.2: DAEMON-16, DAEMON-31, DAEMON-40, DAEMON-45, DAEMON-49, DAEMON-60,
        DAEMON-84, DAEMON-90, DAEMON-91, DAEMON-92, DAEMON-93, DAEMON-94,

Modified: commons/proper/daemon/trunk/src/native/nt/procrun/src/service.c
URL: 
http://svn.apache.org/viewvc/commons/proper/daemon/trunk/src/native/nt/procrun/src/service.c?rev=923104&r1=923103&r2=923104&view=diff
==============================================================================
--- commons/proper/daemon/trunk/src/native/nt/procrun/src/service.c (original)
+++ commons/proper/daemon/trunk/src/native/nt/procrun/src/service.c Mon Mar 15 
07:41:49 2010
@@ -235,6 +235,104 @@ apxServiceSetOptions(APXHANDLE hService,
                                NULL, NULL);
 }
 
+static BOOL
+__apxStopDependentServices(LPAPXSERVICE lpService)
+{
+    DWORD i;
+    DWORD dwBytesNeeded;
+    DWORD dwCount;
+
+    LPENUM_SERVICE_STATUS   lpDependencies = NULL;
+    ENUM_SERVICE_STATUS     ess;
+    SC_HANDLE               hDepService;
+    SERVICE_STATUS_PROCESS  ssp;
+
+    DWORD dwStartTime = GetTickCount();
+    /* Use the 30-second time-out */
+    DWORD dwTimeout   = 30000;
+
+    /* Pass a zero-length buffer to get the required buffer size.
+     */
+    if (EnumDependentServices(lpService->hService,
+                              SERVICE_ACTIVE,
+                              lpDependencies, 0,
+                              &dwBytesNeeded,
+                              &dwCount)) {
+         /* If the Enum call succeeds, then there are no dependent
+          * services, so do nothing.
+          */
+         return TRUE;
+    }
+    else  {
+        if (GetLastError() != ERROR_MORE_DATA)
+            return FALSE; // Unexpected error
+
+        /* Allocate a buffer for the dependencies.
+         */
+        lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc(GetProcessHeap(),
+                                                           HEAP_ZERO_MEMORY,
+                                                           dwBytesNeeded);
+        if (!lpDependencies)
+            return FALSE;
+
+        __try {
+            /* Enumerate the dependencies. */
+            if (!EnumDependentServices(lpService->hService,
+                                       SERVICE_ACTIVE,
+                                       lpDependencies,
+                                       dwBytesNeeded,
+                                      &dwBytesNeeded,
+                                      &dwCount))
+            return FALSE;
+
+            for (i = 0; i < dwCount; i++)  {
+                ess = *(lpDependencies + i);
+                /* Open the service. */
+                hDepService = OpenService(lpService->hManager,
+                                          ess.lpServiceName,
+                                          SERVICE_STOP | SERVICE_QUERY_STATUS);
+
+                if (!hDepService)
+                   return FALSE;
+
+                __try {
+                    /* Send a stop code. */
+                    if (!ControlService(hDepService,
+                                        SERVICE_CONTROL_STOP,
+                                        (LPSERVICE_STATUS) &ssp))
+                    return FALSE;
+
+                    /* Wait for the service to stop. */
+                    while (ssp.dwCurrentState != SERVICE_STOPPED) {
+                        Sleep(ssp.dwWaitHint);
+                        if (!QueryServiceStatusEx(hDepService,
+                                                  SC_STATUS_PROCESS_INFO,
+                                                 (LPBYTE)&ssp,
+                                                  
sizeof(SERVICE_STATUS_PROCESS),
+                                                 &dwBytesNeeded))
+                        return FALSE;
+
+                        if (ssp.dwCurrentState == SERVICE_STOPPED)
+                            break;
+
+                        if (GetTickCount() - dwStartTime > dwTimeout)
+                            return FALSE;
+                    }
+                }
+                __finally {
+                    /* Always release the service handle. */
+                    CloseServiceHandle(hDepService);
+                }
+            }
+        }
+        __finally {
+            /* Always free the enumeration buffer. */
+            HeapFree(GetProcessHeap(), 0, lpDependencies);
+        }
+    }
+    return TRUE;
+}
+
 BOOL
 apxServiceControl(APXHANDLE hService, DWORD dwControl, UINT uMsg,
                   LPAPXFNCALLBACK fnControlCallback,
@@ -313,8 +411,16 @@ apxServiceControl(APXHANDLE hService, DW
     if (dwControl == SERVICE_CONTROL_CONTINUE &&
         stStatus.dwCurrentState != SERVICE_PAUSED)
         bStatus = StartService(lpService->hService, 0, NULL);
-    else
-        bStatus = ControlService(lpService->hService, dwControl, &stStatus);
+    else {
+        bStatus = TRUE;
+        if (dwControl == SERVICE_CONTROL_STOP) {
+            /* First stop dependent services
+             */
+            bStatus = __apxStopDependentServices(lpService);
+        }
+        if (bStatus)
+            bStatus = ControlService(lpService->hService, dwControl, 
&stStatus);
+    }
     dwStart = GetTickCount();
     dwCheck = stStatus.dwCheckPoint;
     if (bStatus) {


Reply via email to