rpcrt4: Fix a race when server grabs a connection from the list of active connections.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ab2760ec33
commit
e889b027ef
|
@ -3373,40 +3373,50 @@ void rpcrt4_conn_release_and_wait(RpcConnection *connection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn )
|
RpcConnection *RPCRT4_GrabConnection(RpcConnection *connection)
|
||||||
{
|
{
|
||||||
InterlockedIncrement( &conn->ref );
|
LONG ref = InterlockedIncrement(&connection->ref);
|
||||||
return conn;
|
TRACE("%p ref=%u\n", connection, ref);
|
||||||
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection)
|
RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection *connection)
|
||||||
{
|
{
|
||||||
if (InterlockedDecrement( &Connection->ref ) > 0) return RPC_S_OK;
|
LONG ref = InterlockedDecrement(&connection->ref);
|
||||||
|
|
||||||
TRACE("destroying connection %p\n", Connection);
|
if (!ref && connection->protseq)
|
||||||
|
{
|
||||||
|
/* protseq stores a list of active connections, but does not own references to them.
|
||||||
|
* It may need to grab a connection from the list, which could lead to a race if
|
||||||
|
* connection is being released, but not yet removed from the list. We handle that
|
||||||
|
* by synchronizing on CS here. */
|
||||||
|
EnterCriticalSection(&connection->protseq->cs);
|
||||||
|
ref = connection->ref;
|
||||||
|
if (!ref)
|
||||||
|
list_remove(&connection->protseq_entry);
|
||||||
|
LeaveCriticalSection(&connection->protseq->cs);
|
||||||
|
}
|
||||||
|
|
||||||
RPCRT4_CloseConnection(Connection);
|
TRACE("%p ref=%u\n", connection, ref);
|
||||||
RPCRT4_strfree(Connection->Endpoint);
|
|
||||||
RPCRT4_strfree(Connection->NetworkAddr);
|
|
||||||
HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions);
|
|
||||||
HeapFree(GetProcessHeap(), 0, Connection->CookieAuth);
|
|
||||||
if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
|
|
||||||
if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
|
|
||||||
|
|
||||||
/* server-only */
|
if (!ref)
|
||||||
if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding);
|
{
|
||||||
|
RPCRT4_CloseConnection(connection);
|
||||||
|
RPCRT4_strfree(connection->Endpoint);
|
||||||
|
RPCRT4_strfree(connection->NetworkAddr);
|
||||||
|
HeapFree(GetProcessHeap(), 0, connection->NetworkOptions);
|
||||||
|
HeapFree(GetProcessHeap(), 0, connection->CookieAuth);
|
||||||
|
if (connection->AuthInfo) RpcAuthInfo_Release(connection->AuthInfo);
|
||||||
|
if (connection->QOS) RpcQualityOfService_Release(connection->QOS);
|
||||||
|
|
||||||
if (Connection->protseq)
|
/* server-only */
|
||||||
{
|
if (connection->server_binding) RPCRT4_ReleaseBinding(connection->server_binding);
|
||||||
EnterCriticalSection(&Connection->protseq->cs);
|
|
||||||
list_remove(&Connection->protseq_entry);
|
|
||||||
LeaveCriticalSection(&Connection->protseq->cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Connection->wait_release) SetEvent(Connection->wait_release);
|
if (connection->wait_release) SetEvent(connection->wait_release);
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, Connection);
|
HeapFree(GetProcessHeap(), 0, connection);
|
||||||
return RPC_S_OK;
|
}
|
||||||
|
return RPC_S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RPC_STATUS RPCRT4_IsServerListening(const char *protseq, const char *endpoint)
|
RPC_STATUS RPCRT4_IsServerListening(const char *protseq, const char *endpoint)
|
||||||
|
|
Loading…
Reference in New Issue