mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 19:45:34 +00:00
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:
parent
d98194e791
commit
00b1184f10
|
@ -1137,7 +1137,8 @@ DWORD __cdecl svcctl_ControlService(
|
||||||
break;
|
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;
|
result = ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
|
||||||
service_terminate(service->service_entry);
|
service_terminate(service->service_entry);
|
||||||
}
|
}
|
||||||
|
@ -1164,45 +1165,35 @@ DWORD __cdecl svcctl_ControlService(
|
||||||
return ERROR_INVALID_SERVICE_CONTROL;
|
return ERROR_INVALID_SERVICE_CONTROL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prevent races by caching control_mutex and clearing it on
|
/* Remember that we tried to shutdown this service. When the service is
|
||||||
* stop instead of outside the services lock */
|
* still running on the second invocation, it will be forcefully killed. */
|
||||||
control_mutex = service->service_entry->control_mutex;
|
|
||||||
if (dwControl == SERVICE_CONTROL_STOP)
|
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);
|
service_unlock(service->service_entry);
|
||||||
|
|
||||||
ret = WaitForSingleObject(control_mutex, 30000);
|
ret = WaitForSingleObject(control_mutex, 30000);
|
||||||
if (ret == WAIT_OBJECT_0)
|
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 (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;
|
return ERROR_SERVICE_REQUEST_TIMEOUT;
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReleaseMutex(control_mutex);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD __cdecl svcctl_CloseServiceHandle(
|
DWORD __cdecl svcctl_CloseServiceHandle(
|
||||||
|
|
|
@ -852,6 +852,7 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
|
||||||
|
|
||||||
CloseHandle(service->control_pipe);
|
CloseHandle(service->control_pipe);
|
||||||
service->control_mutex = CreateMutexW(NULL, TRUE, NULL);
|
service->control_mutex = CreateMutexW(NULL, TRUE, NULL);
|
||||||
|
service->force_shutdown = FALSE;
|
||||||
|
|
||||||
if (!service->status_changed_event)
|
if (!service->status_changed_event)
|
||||||
service->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
service->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
|
@ -48,6 +48,7 @@ struct service_entry
|
||||||
HANDLE control_pipe;
|
HANDLE control_pipe;
|
||||||
HANDLE overlapped_event;
|
HANDLE overlapped_event;
|
||||||
HANDLE status_changed_event;
|
HANDLE status_changed_event;
|
||||||
|
BOOL force_shutdown;
|
||||||
BOOL marked_for_delete;
|
BOOL marked_for_delete;
|
||||||
BOOL is_wow64;
|
BOOL is_wow64;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue