https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f6d81f225747e4b1b3716…
commit f6d81f225747e4b1b3716e9ca8629f77dcc52b1a
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Fri Oct 5 08:41:23 2018 +0200
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Fri Oct 5 08:41:23 2018 +0200
[SERVICES] Fix timeout when a service is stopped
RSetServiceStatus: Send the stop command for the dispatcher thread from a separate
thread.
Fixes CORE-15064
---
base/system/services/rpcserver.c | 59 ++++++++++++++++++++++++++++++++++------
1 file changed, 50 insertions(+), 9 deletions(-)
diff --git a/base/system/services/rpcserver.c b/base/system/services/rpcserver.c
index 7f251c8760..8e383a5bdc 100644
--- a/base/system/services/rpcserver.c
+++ b/base/system/services/rpcserver.c
@@ -1671,6 +1671,43 @@ ScmIsValidServiceState(DWORD dwCurrentState)
}
+static
+DWORD
+WINAPI
+ScmStopThread(
+ _In_ PVOID pParam)
+{
+ PSERVICE pService;
+
+ DPRINT("ScmStopThread(%p)\n", pParam);
+
+ pService = (PSERVICE)pParam;
+
+ if (pService->lpImage->dwImageRunCount != 0)
+ return 0;
+
+ Sleep(2000);
+
+ /* Lock the service database exclusively */
+ ScmLockDatabaseExclusive();
+
+ /* Stop the dispatcher thread */
+ ScmControlService(pService->lpImage->hControlPipe,
+ L"",
+ (SERVICE_STATUS_HANDLE)pService,
+ SERVICE_CONTROL_STOP);
+
+ /* Remove the service image */
+ ScmRemoveServiceImage(pService->lpImage);
+
+ /* Unlock the service database */
+ ScmUnlockDatabase();
+
+ DPRINT("ScmStopThread done!\n");
+ return 0;
+}
+
+
/* Function 7 */
DWORD
WINAPI
@@ -1683,6 +1720,8 @@ RSetServiceStatus(
DWORD dwPreviousType;
LPCWSTR lpLogStrings[2];
WCHAR szLogBuffer[80];
+ HANDLE hStopThread = NULL;
+ DWORD dwStopThreadId;
UINT uID;
DPRINT("RSetServiceStatus() called\n");
@@ -1762,15 +1801,17 @@ RSetServiceStatus(
/* If we just stopped the last running service... */
if (lpService->lpImage->dwImageRunCount == 0)
{
- /* Stop the dispatcher thread */
- ScmControlService(lpService->lpImage->hControlPipe,
- L"",
- (SERVICE_STATUS_HANDLE)lpService,
- SERVICE_CONTROL_STOP);
-
- /* Remove the service image */
- ScmRemoveServiceImage(lpService->lpImage);
- lpService->lpImage = NULL;
+ /* Run the stop thread to stop the service dispatcher */
+ hStopThread = CreateThread(NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)ScmStopThread,
+ (LPVOID)lpService,
+ 0,
+ &dwStopThreadId);
+ if (hStopThread != NULL)
+ {
+ CloseHandle(hStopThread);
+ }
}
}