services: Store a separate variable instead of clearing control_mutex.

Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Sebastian Lackner 2016-03-03 06:26:26 +01:00 committed by Alexandre Julliard
parent d98194e791
commit 00b1184f10
3 changed files with 26 additions and 33 deletions

View File

@ -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,17 +1165,18 @@ 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)
{
if (ret != WAIT_OBJECT_0)
return ERROR_SERVICE_REQUEST_TIMEOUT;
service_send_control(service->service_entry, dwControl, &result);
if (lpServiceStatus)
@ -1190,20 +1192,9 @@ DWORD __cdecl svcctl_ControlService(
service_unlock(service->service_entry);
}
if (dwControl == SERVICE_CONTROL_STOP)
CloseHandle(control_mutex);
else
ReleaseMutex(control_mutex);
return result;
}
else
{
if (dwControl == SERVICE_CONTROL_STOP)
CloseHandle(control_mutex);
return ERROR_SERVICE_REQUEST_TIMEOUT;
}
}
DWORD __cdecl svcctl_CloseServiceHandle(
SC_RPC_HANDLE *handle)

View File

@ -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);

View File

@ -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;
};