Module: wine Branch: master Commit: 00b1184f1092ecc6ab6b7ef7a9e6213c4b6fc54c URL: http://source.winehq.org/git/wine.git/?a=commit;h=00b1184f1092ecc6ab6b7ef7a9...
Author: Sebastian Lackner sebastian@fds-team.de Date: Thu Mar 3 06:26:26 2016 +0100
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
---
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; };