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) {