[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