Module: wine Branch: master Commit: fac8ec93893a156842f344e669aa1360b219a18a URL: http://source.winehq.org/git/wine.git/?a=commit;h=fac8ec93893a156842f344e669...
Author: Sebastian Lackner sebastian@fds-team.de Date: Thu Aug 11 07:21:49 2016 +0200
services: Unlink process immediately after service stopped.
Signed-off-by: Sebastian Lackner sebastian@fds-team.de Signed-off-by: Alexandre Julliard julliard@winehq.org
---
programs/services/rpc.c | 20 ++++++++++---------- programs/services/tests/service.c | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/programs/services/rpc.c b/programs/services/rpc.c index 36a0620..102b3b5 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -100,21 +100,17 @@ struct timeout_queue_elem struct list entry;
FILETIME time; - void (*func)(struct process_entry *); struct process_entry *process; };
-static void run_after_timeout(void (*func)(struct process_entry *), struct process_entry *process, DWORD timeout) +static void terminate_after_timeout(struct process_entry *process, DWORD timeout) { - struct timeout_queue_elem *elem = HeapAlloc(GetProcessHeap(), 0, sizeof(struct timeout_queue_elem)); + struct timeout_queue_elem *elem; ULARGE_INTEGER time;
- if(!elem) { - func(process); + if (!(elem = HeapAlloc(GetProcessHeap(), 0, sizeof(*elem)))) return; - }
- elem->func = func; elem->process = grab_process(process);
GetSystemTimeAsFileTime(&elem->time); @@ -765,7 +761,11 @@ DWORD __cdecl svcctl_SetServiceStatus( if ((process = service->service_entry->process)) { if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED) - run_after_timeout(process_terminate, process, service_kill_timeout); + { + service->service_entry->process = NULL; + terminate_after_timeout(process, service_kill_timeout); + release_process(process); + } else SetEvent(process->status_changed_event); } @@ -1943,7 +1943,7 @@ DWORD events_loop(void) (err > WAIT_OBJECT_0 + 1 && idx == err - WAIT_OBJECT_0 - 2)) { LeaveCriticalSection(&timeout_queue_cs); - iter->func(iter->process); + process_terminate(iter->process); EnterCriticalSection(&timeout_queue_cs);
release_process(iter->process); @@ -1975,7 +1975,7 @@ DWORD events_loop(void) LIST_FOR_EACH_ENTRY_SAFE(iter, iter_safe, &timeout_queue, struct timeout_queue_elem, entry) { LeaveCriticalSection(&timeout_queue_cs); - iter->func(iter->process); + process_terminate(iter->process); EnterCriticalSection(&timeout_queue_cs);
release_process(iter->process); diff --git a/programs/services/tests/service.c b/programs/services/tests/service.c index fea6363..b184bda 100644 --- a/programs/services/tests/service.c +++ b/programs/services/tests/service.c @@ -321,7 +321,9 @@ static DWORD WINAPI pipe_thread(void *arg) static void test_service(void) { SC_HANDLE service_handle = register_service("simple_service"); + SERVICE_STATUS_PROCESS status2; SERVICE_STATUS status; + DWORD bytes; BOOL res;
if(!service_handle) @@ -349,6 +351,11 @@ static void test_service(void) ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint); todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
+ res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes); + ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError()); + ok(status2.dwCurrentState == SERVICE_RUNNING, "status2.dwCurrentState = %x\n", status2.dwCurrentState); + ok(status2.dwProcessId != 0, "status2.dwProcessId = %d\n", status2.dwProcessId); + res = ControlService(service_handle, 128, &status); ok(res, "ControlService failed: %u\n", GetLastError()); expect_event("CUSTOM"); @@ -366,7 +373,9 @@ static void test_service(void) static inline void test_no_stop(void) { SC_HANDLE service_handle = register_service("no_stop"); + SERVICE_STATUS_PROCESS status2; SERVICE_STATUS status; + DWORD bytes; BOOL res;
if(!service_handle) @@ -397,6 +406,11 @@ static inline void test_no_stop(void) ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint); todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
+ res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes); + ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError()); + ok(status2.dwCurrentState == SERVICE_RUNNING, "status2.dwCurrentState = %x\n", status2.dwCurrentState); + ok(status2.dwProcessId != 0, "status2.dwProcessId = %d\n", status2.dwProcessId); + res = ControlService(service_handle, SERVICE_CONTROL_STOP, &status); ok(res, "ControlService failed: %u\n", GetLastError()); expect_event("STOP"); @@ -413,6 +427,11 @@ static inline void test_no_stop(void) ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint); ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
+ res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes); + ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError()); + ok(status2.dwProcessId == 0 || broken(status2.dwProcessId != 0), + "status2.dwProcessId = %d\n", status2.dwProcessId); + res = DeleteService(service_handle); ok(res, "DeleteService failed: %u\n", GetLastError());
@@ -428,6 +447,11 @@ static inline void test_no_stop(void) ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint); ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
+ res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes); + ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError()); + ok(status2.dwProcessId == 0 || broken(status2.dwProcessId != 0), + "status2.dwProcessId = %d\n", status2.dwProcessId); + CloseServiceHandle(service_handle);
res = QueryServiceStatus(service_handle, &status);