From b3d436b8fa66048482353c96fcf70383684daf3d Mon Sep 17 00:00:00 2001 From: Mikolaj Zalewski Date: Wed, 26 Sep 2007 12:53:20 -0700 Subject: [PATCH] advapi32: exit the service process when the last service thread stops --- dlls/advapi32/service.c | 68 ++++++++++++++++++++++++----------------------- 1 files changed, 34 insertions(+), 34 deletions(-) diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 666be6e..b1d32ca 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -60,6 +60,9 @@ static const GENERIC_MAPPING svc_generic SERVICE_ALL_ACCESS }; +static ULONG g_num_services = 0; +static HANDLE g_no_services_event; + typedef struct service_start_info_t { DWORD cmd; @@ -387,16 +390,24 @@ static DWORD WINAPI service_thread(LPVOI argc++; } + EnterCriticalSection(&service_cs); + if (WaitForSingleObject(g_no_services_event, 0) == WAIT_OBJECT_0) + { + /* possible race condition - request while process is shutting down */ + LeaveCriticalSection(&service_cs); + return ERROR_SERVICE_CANNOT_ACCEPT_CTRL; + } + g_num_services++; + LeaveCriticalSection(&service_cs); + if (!argc) { if (info->unicode) info->proc.w(0, NULL); else info->proc.a(0, NULL); - return 0; } - - if (info->unicode) + else if (info->unicode) { LPWSTR *argv, p; @@ -426,6 +437,15 @@ static DWORD WINAPI service_thread(LPVOI HeapFree(GetProcessHeap(), 0, argv); HeapFree(GetProcessHeap(), 0, strA); } + TRACE("Service main exited\n"); + + EnterCriticalSection(&service_cs); + if (--g_num_services == 0) + { + SetEvent(g_no_services_event); + TRACE("Last service stopped - process shutdown\n"); + } + LeaveCriticalSection(&service_cs); return 0; } @@ -752,50 +772,30 @@ static DWORD WINAPI service_control_disp static BOOL service_run_threads(void) { service_data *service; - DWORD count, n = 0; - HANDLE *handles; - - EnterCriticalSection( &service_cs ); - - count = list_count( &service_list ); + HANDLE handles[2]; - TRACE("Starting %d pipe listener threads. Services running as process %d\n", count, GetCurrentProcessId()); + g_no_services_event = CreateEventW(NULL, TRUE, FALSE, NULL); - handles = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLE) * (count + 1)); + EnterCriticalSection( &service_cs ); - handles[n++] = __wine_make_process_system(); + TRACE("Starting pipe listener threads. Services running as process %d\n", GetCurrentProcessId()); LIST_FOR_EACH_ENTRY( service, &service_list, service_data, entry ) { + HANDLE thread; service->status.dwProcessId = GetCurrentProcessId(); - handles[n++] = CreateThread( NULL, 0, service_control_dispatcher, + thread = CreateThread( NULL, 0, service_control_dispatcher, service, 0, NULL ); + CloseHandle(thread); } - assert(n == count + 1); LeaveCriticalSection( &service_cs ); - /* wait for all the threads to pack up and exit */ - while (n > 1) - { - DWORD ret = WaitForMultipleObjects( min(n,MAXIMUM_WAIT_OBJECTS), handles, FALSE, INFINITE ); - if (!ret) /* system process event */ - { - TRACE( "last user process exited, shutting down\n" ); - /* FIXME: we should maybe send a shutdown control to running services */ - ExitProcess(0); - } - if (ret < MAXIMUM_WAIT_OBJECTS) - { - CloseHandle( handles[ret] ); - memmove( &handles[ret], &handles[ret+1], (n - ret - 1) * sizeof(HANDLE) ); - n--; - } - else break; - } + handles[0] = __wine_make_process_system(); + handles[1] = g_no_services_event; - while (n) CloseHandle( handles[--n] ); - HeapFree(GetProcessHeap(), 0, handles); + /* wait for all the threads to pack up and exit */ + WaitForMultipleObjects(2, handles, FALSE, INFINITE); return TRUE; } -- 1.4.1