Sebastian Lackner : services: Unlink process immediately after service stopped.

Alexandre Julliard julliard at winehq.org
Thu Aug 11 09:37:48 CDT 2016


Module: wine
Branch: master
Commit: fac8ec93893a156842f344e669aa1360b219a18a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=fac8ec93893a156842f344e669aa1360b219a18a

Author: Sebastian Lackner <sebastian at 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 at fds-team.de>
Signed-off-by: Alexandre Julliard <julliard at 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);




More information about the wine-cvs mailing list