[2/3] services: Allocate a separate status_changed_event for each service.

Sebastian Lackner sebastian at fds-team.de
Fri Aug 19 01:01:03 CDT 2016


Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---

This partially reverts changes from ed54b881738c616674d7025b32f704a159decd4a and
7fc3f72de77d0ab69a91f9efc38c78956de7bffb. With a single status changed event per
process we cannot really determine what has changed, which would make other parts
unnecessarily complex. This patch also changes the event to manual-reset and adds
a call to ResetEvent() to make sure we get the event we're interested in.

 programs/services/rpc.c      |   20 ++++++++++----------
 programs/services/services.c |   42 ++++++++++++++++++++----------------------
 programs/services/services.h |    2 +-
 3 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 4c6301c..688e4a0 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -758,21 +758,21 @@ DWORD __cdecl svcctl_SetServiceStatus(
         return err;
 
     service_lock(service->service_entry);
+
     /* FIXME: be a bit more discriminant about what parts of the status we set
      * and check that fields are valid */
     service->service_entry->status = *lpServiceStatus;
-    if ((process = service->service_entry->process))
+    SetEvent(service->service_entry->status_changed_event);
+
+    if ((process = service->service_entry->process) &&
+        lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
     {
-        if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
-        {
-            service->service_entry->process = NULL;
-            if (!--process->use_count)
-                terminate_after_timeout(process, service_kill_timeout);
-            release_process(process);
-        }
-        else
-            SetEvent(process->status_changed_event);
+        service->service_entry->process = NULL;
+        if (!--process->use_count)
+            terminate_after_timeout(process, service_kill_timeout);
+        release_process(process);
     }
+
     service_unlock(service->service_entry);
 
     return ERROR_SUCCESS;
diff --git a/programs/services/services.c b/programs/services/services.c
index 409f2ee..dacca82 100644
--- a/programs/services/services.c
+++ b/programs/services/services.c
@@ -82,9 +82,6 @@ static DWORD process_create(const WCHAR *name, struct process_entry **entry)
     (*entry)->overlapped_event = CreateEventW(NULL, TRUE, FALSE, NULL);
     if (!(*entry)->overlapped_event)
         goto error;
-    (*entry)->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-    if (!(*entry)->status_changed_event)
-        goto error;
     (*entry)->control_pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
                                               PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL);
     if ((*entry)->control_pipe == INVALID_HANDLE_VALUE)
@@ -98,8 +95,6 @@ error:
         CloseHandle((*entry)->control_mutex);
     if ((*entry)->overlapped_event)
         CloseHandle((*entry)->overlapped_event);
-    if ((*entry)->status_changed_event)
-        CloseHandle((*entry)->status_changed_event);
     HeapFree(GetProcessHeap(), 0, *entry);
     return err;
 }
@@ -110,7 +105,6 @@ static void free_process_entry(struct process_entry *entry)
     CloseHandle(entry->control_mutex);
     CloseHandle(entry->control_pipe);
     CloseHandle(entry->overlapped_event);
-    CloseHandle(entry->status_changed_event);
     HeapFree(GetProcessHeap(), 0, entry);
 }
 
@@ -125,6 +119,13 @@ DWORD service_create(LPCWSTR name, struct service_entry **entry)
         HeapFree(GetProcessHeap(), 0, *entry);
         return ERROR_NOT_ENOUGH_SERVER_MEMORY;
     }
+    (*entry)->status_changed_event = CreateEventW(NULL, TRUE, FALSE, NULL);
+    if (!(*entry)->status_changed_event)
+    {
+        HeapFree(GetProcessHeap(), 0, (*entry)->name);
+        HeapFree(GetProcessHeap(), 0, *entry);
+        return GetLastError();
+    }
     (*entry)->ref_count = 1;
     (*entry)->status.dwCurrentState = SERVICE_STOPPED;
     (*entry)->status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED;
@@ -135,6 +136,7 @@ DWORD service_create(LPCWSTR name, struct service_entry **entry)
 
 void free_service_entry(struct service_entry *entry)
 {
+    CloseHandle(entry->status_changed_event);
     HeapFree(GetProcessHeap(), 0, entry->name);
     HeapFree(GetProcessHeap(), 0, entry->config.lpBinaryPathName);
     HeapFree(GetProcessHeap(), 0, entry->config.lpDependencies);
@@ -790,6 +792,9 @@ static DWORD service_start_process(struct service_entry *service_entry, struct p
     }
 
     service_entry->status.dwCurrentState = SERVICE_START_PENDING;
+    service_entry->status.dwControlsAccepted = 0;
+    ResetEvent(service_entry->status_changed_event);
+
     scmdatabase_add_process(service_entry->db, process);
     service_entry->process = grab_process(process);
     process->use_count++;
@@ -814,24 +819,20 @@ static DWORD service_start_process(struct service_entry *service_entry, struct p
     return ERROR_SUCCESS;
 }
 
-static DWORD process_wait_for_startup(struct process_entry *process)
+static DWORD service_wait_for_startup(struct service_entry *service, struct process_entry *process)
 {
-    HANDLE handles[2] = { process->status_changed_event, process->process };
-    DWORD ret;
+    HANDLE handles[2] = { service->status_changed_event, process->process };
+    DWORD result;
 
-    ret = WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout );
-    return (ret == WAIT_OBJECT_0) ? ERROR_SUCCESS : ERROR_SERVICE_REQUEST_TIMEOUT;
-}
-
-static DWORD service_is_running(struct service_entry *service)
-{
-    DWORD state;
+    result = WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout );
+    if (result != WAIT_OBJECT_0)
+        return ERROR_SERVICE_REQUEST_TIMEOUT;
 
     service_lock(service);
-    state = service->status.dwCurrentState;
+    result = service->status.dwCurrentState;
     service_unlock(service);
 
-    return (state == SERVICE_START_PENDING || state == SERVICE_RUNNING) ?
+    return (result == SERVICE_START_PENDING || result == SERVICE_RUNNING) ?
            ERROR_SUCCESS : ERROR_SERVICE_REQUEST_TIMEOUT;
 }
 
@@ -911,10 +912,7 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
         err = process_send_start_message(process, service->name, service_argv, service_argc);
 
         if (err == ERROR_SUCCESS)
-            err = process_wait_for_startup(process);
-
-        if (err == ERROR_SUCCESS)
-            err = service_is_running(service);
+            err = service_wait_for_startup(service, process);
 
         if (err == ERROR_SUCCESS)
             ReleaseMutex(process->control_mutex);
diff --git a/programs/services/services.h b/programs/services/services.h
index 417efcd..b03a157 100644
--- a/programs/services/services.h
+++ b/programs/services/services.h
@@ -43,7 +43,6 @@ struct process_entry
     HANDLE control_mutex;
     HANDLE control_pipe;
     HANDLE overlapped_event;
-    HANDLE status_changed_event;
 };
 
 struct service_entry
@@ -53,6 +52,7 @@ struct service_entry
     LONG ref_count;                    /* number of references - if goes to zero and the service is deleted the structure will be freed */
     LPWSTR name;
     SERVICE_STATUS status;
+    HANDLE status_changed_event;
     QUERY_SERVICE_CONFIGW config;
     DWORD preshutdown_timeout;
     LPWSTR description;
-- 
2.9.0



More information about the wine-patches mailing list