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