[PATCH 1/3] services: Monitor process handles for process quit

Andrew Eikum aeikum at codeweavers.com
Wed Feb 25 14:28:31 CST 2015


Without this change, the services program will hold onto a service
handle for 60 seconds after calling
ControlService(SERVICE_CONTROL_STOP), even if the process exits
immediately. This has the effect of causing a service to be "in use"
for 60 seconds, preventing actions like DeleteService from succeeding
in a timely fashion.

The tests in the following patches fail without this change as the
service doesn't get removed quickly enough.
---
 programs/services/rpc.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 3a206c7..2a13c93 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -1622,10 +1622,12 @@ DWORD RPC_Init(void)
 DWORD events_loop(void)
 {
     struct timeout_queue_elem *iter, *iter_safe;
-    DWORD err;
-    HANDLE wait_handles[2];
+    DWORD err, max_handles = 3, num_handles = 2;
+    HANDLE *wait_handles;
     DWORD timeout = INFINITE;
 
+    wait_handles = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLE) * max_handles);
+
     wait_handles[0] = __wine_make_process_system();
     wait_handles[1] = CreateEventW(NULL, FALSE, FALSE, NULL);
     timeout_queue_event = wait_handles[1];
@@ -1636,13 +1638,30 @@ DWORD events_loop(void)
 
     do
     {
-        err = WaitForMultipleObjects(2, wait_handles, FALSE, timeout);
+        num_handles = 2;
+
+        /* monitor tracked process handles for process end */
+        EnterCriticalSection(&timeout_queue_cs);
+        LIST_FOR_EACH_ENTRY(iter, &timeout_queue, struct timeout_queue_elem, entry)
+        {
+            if(num_handles == max_handles)
+            {
+                max_handles++;
+                wait_handles = HeapReAlloc(GetProcessHeap(), 0, wait_handles, sizeof(HANDLE) * max_handles);
+            }
+            wait_handles[num_handles] = iter->service_entry->process;
+            num_handles++;
+        }
+        LeaveCriticalSection(&timeout_queue_cs);
+
+        err = WaitForMultipleObjects(num_handles, wait_handles, FALSE, timeout);
         WINE_TRACE("Wait returned %d\n", err);
 
-        if(err==WAIT_OBJECT_0+1 || err==WAIT_TIMEOUT)
+        if(err > WAIT_OBJECT_0 || err == WAIT_TIMEOUT)
         {
             FILETIME cur_time;
             ULARGE_INTEGER time;
+            DWORD idx = 0;
 
             GetSystemTimeAsFileTime(&cur_time);
             time.u.LowPart = cur_time.dwLowDateTime;
@@ -1652,7 +1671,8 @@ DWORD events_loop(void)
             timeout = INFINITE;
             LIST_FOR_EACH_ENTRY_SAFE(iter, iter_safe, &timeout_queue, struct timeout_queue_elem, entry)
             {
-                if(CompareFileTime(&cur_time, &iter->time) >= 0)
+                if(CompareFileTime(&cur_time, &iter->time) >= 0 ||
+                        (err > WAIT_OBJECT_0 + 1 && idx == err - WAIT_OBJECT_0 - 2))
                 {
                     LeaveCriticalSection(&timeout_queue_cs);
                     iter->func(iter->service_entry);
@@ -1673,6 +1693,7 @@ DWORD events_loop(void)
                     if(time_diff.QuadPart < timeout)
                         timeout = time_diff.QuadPart;
                 }
+                idx++;
             }
             LeaveCriticalSection(&timeout_queue_cs);
 
@@ -1697,6 +1718,7 @@ DWORD events_loop(void)
 
     CloseHandle(wait_handles[0]);
     CloseHandle(wait_handles[1]);
+    HeapFree(GetProcessHeap(), 0, wait_handles);
     return ERROR_SUCCESS;
 }
 
-- 
2.3.0





More information about the wine-patches mailing list