[3/4] services: Store a separate variable instead of clearing control_mutex.

Sebastian Lackner sebastian at fds-team.de
Wed Mar 2 23:26:26 CST 2016


Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---
 programs/services/rpc.c      |   53 +++++++++++++++++--------------------------
 programs/services/services.c |    1 
 programs/services/services.h |    1 
 3 files changed, 24 insertions(+), 31 deletions(-)

diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 6951fb8..ece8dce 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -1137,7 +1137,8 @@ DWORD __cdecl svcctl_ControlService(
         break;
     }
 
-    if (result==ERROR_SUCCESS && !service->service_entry->control_mutex) {
+    if (result == ERROR_SUCCESS && service->service_entry->force_shutdown)
+    {
         result = ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
         service_terminate(service->service_entry);
     }
@@ -1164,45 +1165,35 @@ DWORD __cdecl svcctl_ControlService(
         return ERROR_INVALID_SERVICE_CONTROL;
     }
 
-    /* prevent races by caching control_mutex and clearing it on
-     * stop instead of outside the services lock */
-    control_mutex = service->service_entry->control_mutex;
+    /* Remember that we tried to shutdown this service. When the service is
+     * still running on the second invocation, it will be forcefully killed. */
     if (dwControl == SERVICE_CONTROL_STOP)
-        service->service_entry->control_mutex = NULL;
+        service->service_entry->force_shutdown = TRUE;
 
+    control_mutex = service->service_entry->control_mutex;
     service_unlock(service->service_entry);
 
     ret = WaitForSingleObject(control_mutex, 30000);
-    if (ret == WAIT_OBJECT_0)
-    {
-        service_send_control(service->service_entry, dwControl, &result);
-
-        if (lpServiceStatus)
-        {
-            service_lock(service->service_entry);
-            lpServiceStatus->dwServiceType = service->service_entry->status.dwServiceType;
-            lpServiceStatus->dwCurrentState = service->service_entry->status.dwCurrentState;
-            lpServiceStatus->dwControlsAccepted = service->service_entry->status.dwControlsAccepted;
-            lpServiceStatus->dwWin32ExitCode = service->service_entry->status.dwWin32ExitCode;
-            lpServiceStatus->dwServiceSpecificExitCode = service->service_entry->status.dwServiceSpecificExitCode;
-            lpServiceStatus->dwCheckPoint = service->service_entry->status.dwCheckPoint;
-            lpServiceStatus->dwWaitHint = service->service_entry->status.dwWaitHint;
-            service_unlock(service->service_entry);
-        }
+    if (ret != WAIT_OBJECT_0)
+        return ERROR_SERVICE_REQUEST_TIMEOUT;
 
-        if (dwControl == SERVICE_CONTROL_STOP)
-            CloseHandle(control_mutex);
-        else
-            ReleaseMutex(control_mutex);
+    service_send_control(service->service_entry, dwControl, &result);
 
-        return result;
-    }
-    else
+    if (lpServiceStatus)
     {
-        if (dwControl == SERVICE_CONTROL_STOP)
-            CloseHandle(control_mutex);
-        return ERROR_SERVICE_REQUEST_TIMEOUT;
+        service_lock(service->service_entry);
+        lpServiceStatus->dwServiceType = service->service_entry->status.dwServiceType;
+        lpServiceStatus->dwCurrentState = service->service_entry->status.dwCurrentState;
+        lpServiceStatus->dwControlsAccepted = service->service_entry->status.dwControlsAccepted;
+        lpServiceStatus->dwWin32ExitCode = service->service_entry->status.dwWin32ExitCode;
+        lpServiceStatus->dwServiceSpecificExitCode = service->service_entry->status.dwServiceSpecificExitCode;
+        lpServiceStatus->dwCheckPoint = service->service_entry->status.dwCheckPoint;
+        lpServiceStatus->dwWaitHint = service->service_entry->status.dwWaitHint;
+        service_unlock(service->service_entry);
     }
+
+    ReleaseMutex(control_mutex);
+    return result;
 }
 
 DWORD __cdecl svcctl_CloseServiceHandle(
diff --git a/programs/services/services.c b/programs/services/services.c
index c45aed3..02a46f9 100644
--- a/programs/services/services.c
+++ b/programs/services/services.c
@@ -852,6 +852,7 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
 
     CloseHandle(service->control_pipe);
     service->control_mutex = CreateMutexW(NULL, TRUE, NULL);
+    service->force_shutdown = FALSE;
 
     if (!service->status_changed_event)
         service->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
diff --git a/programs/services/services.h b/programs/services/services.h
index a9e6313..7f43b22 100644
--- a/programs/services/services.h
+++ b/programs/services/services.h
@@ -48,6 +48,7 @@ struct service_entry
     HANDLE control_pipe;
     HANDLE overlapped_event;
     HANDLE status_changed_event;
+    BOOL force_shutdown;
     BOOL marked_for_delete;
     BOOL is_wow64;
 };
-- 
2.7.1



More information about the wine-patches mailing list