Module: wine Branch: master Commit: e98c7a59c26bdff7bad27e5864ee7f7ed8313a35 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e98c7a59c26bdff7bad27e5864...
Author: Jacek Caban jacek@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@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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; }