Jacek Caban : rpcrt4: Wait for all active connections to be released before quiting server thread.

Alexandre Julliard julliard at winehq.org
Wed May 31 16:20:18 CDT 2017


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed May 31 17:30:40 2017 +0200

rpcrt4: Wait for all active connections to be released before quiting server thread.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/rpcrt4/rpc_binding.h   |  3 +++
 dlls/rpcrt4/rpc_server.c    | 18 ++++++++++++++++++
 dlls/rpcrt4/rpc_transport.c | 18 ++++++++++++++++++
 3 files changed, 39 insertions(+)

diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h
index affc060..a679b0e 100644
--- a/dlls/rpcrt4/rpc_binding.h
+++ b/dlls/rpcrt4/rpc_binding.h
@@ -63,6 +63,7 @@ typedef struct _RpcConnection
 {
   LONG ref;
   BOOL server;
+  HANDLE wait_release;
   LPSTR NetworkAddr;
   LPSTR Endpoint;
   LPWSTR NetworkOptions;
@@ -176,6 +177,8 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
                               const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RPC_SYNTAX_IDENTIFIER *InterfaceId) DECLSPEC_HIDDEN;
 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) DECLSPEC_HIDDEN;
 
+void rpcrt4_conn_release_and_wait(RpcConnection *connection) DECLSPEC_HIDDEN;
+
 static inline const char *rpcrt4_conn_get_name(const RpcConnection *Connection)
 {
   return Connection->ops->name;
diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c
index d8225f3..bd47de6 100644
--- a/dlls/rpcrt4/rpc_server.c
+++ b/dlls/rpcrt4/rpc_server.c
@@ -675,20 +675,38 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
       set_ready_event = TRUE;
   }
 
+  TRACE("closing connections\n");
+
   EnterCriticalSection(&cps->cs);
   LIST_FOR_EACH_ENTRY(conn, &cps->listeners, RpcConnection, protseq_entry)
     RPCRT4_CloseConnection(conn);
   LIST_FOR_EACH_ENTRY(conn, &cps->connections, RpcConnection, protseq_entry)
+  {
+    RPCRT4_GrabConnection(conn);
     rpcrt4_conn_close_read(conn);
+  }
   LeaveCriticalSection(&cps->cs);
 
   if (res == 0 && !std_listen)
       SetEvent(cps->server_ready_event);
 
+  TRACE("waiting for active connections to close\n");
+
+  EnterCriticalSection(&cps->cs);
+  while (!list_empty(&cps->connections))
+  {
+    conn = LIST_ENTRY(list_head(&cps->connections), RpcConnection, protseq_entry);
+    LeaveCriticalSection(&cps->cs);
+    rpcrt4_conn_release_and_wait(conn);
+    EnterCriticalSection(&cps->cs);
+  }
+  LeaveCriticalSection(&cps->cs);
+
   EnterCriticalSection(&listen_cs);
   CloseHandle(cps->server_thread);
   cps->server_thread = NULL;
   LeaveCriticalSection(&listen_cs);
+  TRACE("done\n");
   return 0;
 }
 
diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c
index 367bf2c..0ae7125 100644
--- a/dlls/rpcrt4/rpc_transport.c
+++ b/dlls/rpcrt4/rpc_transport.c
@@ -3357,6 +3357,22 @@ static RpcConnection *rpcrt4_spawn_connection(RpcConnection *old_connection)
     return connection;
 }
 
+void rpcrt4_conn_release_and_wait(RpcConnection *connection)
+{
+    HANDLE event = NULL;
+
+    if (connection->ref > 1)
+        event = connection->wait_release = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+    RPCRT4_ReleaseConnection(connection);
+
+    if(event)
+    {
+        WaitForSingleObject(event, INFINITE);
+        CloseHandle(event);
+    }
+}
+
 RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn )
 {
     InterlockedIncrement( &conn->ref );
@@ -3387,6 +3403,8 @@ RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection)
     LeaveCriticalSection(&Connection->protseq->cs);
   }
 
+  if (Connection->wait_release) SetEvent(Connection->wait_release);
+
   HeapFree(GetProcessHeap(), 0, Connection);
   return RPC_S_OK;
 }




More information about the wine-cvs mailing list