rpcrt4: Add ref counting to RPC connections, and grab a reference while processing an RPC packet.

This commit is contained in:
Alexandre Julliard 2012-02-14 16:19:32 +01:00
parent e2b38c3ffd
commit d2ca9f4b02
6 changed files with 25 additions and 13 deletions

View file

@ -203,7 +203,7 @@ ULONG RpcAssoc_Release(RpcAssoc *assoc)
LIST_FOR_EACH_ENTRY_SAFE(Connection, cursor2, &assoc->free_connection_pool, RpcConnection, conn_pool_entry) LIST_FOR_EACH_ENTRY_SAFE(Connection, cursor2, &assoc->free_connection_pool, RpcConnection, conn_pool_entry)
{ {
list_remove(&Connection->conn_pool_entry); list_remove(&Connection->conn_pool_entry);
RPCRT4_DestroyConnection(Connection); RPCRT4_ReleaseConnection(Connection);
} }
LIST_FOR_EACH_ENTRY_SAFE(context_handle, context_handle_cursor, &assoc->context_handle_list, RpcContextHandle, entry) LIST_FOR_EACH_ENTRY_SAFE(context_handle, context_handle_cursor, &assoc->context_handle_list, RpcContextHandle, entry)
@ -410,14 +410,14 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc,
status = RPCRT4_OpenClientConnection(NewConnection); status = RPCRT4_OpenClientConnection(NewConnection);
if (status != RPC_S_OK) if (status != RPC_S_OK)
{ {
RPCRT4_DestroyConnection(NewConnection); RPCRT4_ReleaseConnection(NewConnection);
return status; return status;
} }
status = RpcAssoc_BindConnection(assoc, NewConnection, InterfaceId, TransferSyntax); status = RpcAssoc_BindConnection(assoc, NewConnection, InterfaceId, TransferSyntax);
if (status != RPC_S_OK) if (status != RPC_S_OK)
{ {
RPCRT4_DestroyConnection(NewConnection); RPCRT4_ReleaseConnection(NewConnection);
return status; return status;
} }

View file

@ -298,7 +298,7 @@ RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
/* don't destroy a connection that is cached in the binding */ /* don't destroy a connection that is cached in the binding */
if (Binding->FromConn == Connection) if (Binding->FromConn == Connection)
return RPC_S_OK; return RPC_S_OK;
return RPCRT4_DestroyConnection(Connection); return RPCRT4_ReleaseConnection(Connection);
} }
else { else {
RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection); RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);

View file

@ -61,6 +61,7 @@ struct connection_ops;
typedef struct _RpcConnection typedef struct _RpcConnection
{ {
LONG ref;
BOOL server; BOOL server;
LPSTR NetworkAddr; LPSTR NetworkAddr;
LPSTR Endpoint; LPSTR Endpoint;
@ -153,7 +154,8 @@ ULONG RpcQualityOfService_Release(RpcQualityOfService *qos) DECLSPEC_HIDDEN;
BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2) DECLSPEC_HIDDEN; BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2) DECLSPEC_HIDDEN;
RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) DECLSPEC_HIDDEN;
RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn ) DECLSPEC_HIDDEN;
RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN;
RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection) DECLSPEC_HIDDEN;
RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN;

View file

@ -1875,7 +1875,7 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
fail: fail:
RPCRT4_FreeHeader(hdr); RPCRT4_FreeHeader(hdr);
RPCRT4_DestroyConnection(conn); RPCRT4_ReleaseConnection(conn);
pMsg->ReservedForRuntime = NULL; pMsg->ReservedForRuntime = NULL;
return status; return status;
} }

View file

@ -539,6 +539,7 @@ static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
RpcPacket *pkt = the_arg; RpcPacket *pkt = the_arg;
RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg, pkt->auth_data, RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg, pkt->auth_data,
pkt->auth_length); pkt->auth_length);
RPCRT4_ReleaseConnection(pkt->conn);
HeapFree(GetProcessHeap(), 0, pkt); HeapFree(GetProcessHeap(), 0, pkt);
return 0; return 0;
} }
@ -585,7 +586,7 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
HeapFree(GetProcessHeap(), 0, auth_data); HeapFree(GetProcessHeap(), 0, auth_data);
goto exit; goto exit;
} }
packet->conn = conn; packet->conn = RPCRT4_GrabConnection( conn );
packet->hdr = hdr; packet->hdr = hdr;
packet->msg = msg; packet->msg = msg;
packet->auth_data = auth_data; packet->auth_data = auth_data;
@ -621,7 +622,7 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
} }
} }
exit: exit:
RPCRT4_DestroyConnection(conn); RPCRT4_ReleaseConnection(conn);
return 0; return 0;
} }
@ -631,7 +632,7 @@ void RPCRT4_new_client(RpcConnection* conn)
if (!thread) { if (!thread) {
DWORD err = GetLastError(); DWORD err = GetLastError();
ERR("failed to create thread, error=%08x\n", err); ERR("failed to create thread, error=%08x\n", err);
RPCRT4_DestroyConnection(conn); RPCRT4_ReleaseConnection(conn);
} }
/* we could set conn->thread, but then we'd have to make the io_thread wait /* we could set conn->thread, but then we'd have to make the io_thread wait
* for that, otherwise the thread might finish, destroy the connection, and * for that, otherwise the thread might finish, destroy the connection, and

View file

@ -1374,7 +1374,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
if (ret < 0) if (ret < 0)
{ {
WARN("listen failed: %s\n", strerror(errno)); WARN("listen failed: %s\n", strerror(errno));
RPCRT4_DestroyConnection(&tcpc->common); RPCRT4_ReleaseConnection(&tcpc->common);
status = RPC_S_OUT_OF_RESOURCES; status = RPC_S_OUT_OF_RESOURCES;
continue; continue;
} }
@ -1387,7 +1387,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
if (ret < 0) if (ret < 0)
{ {
WARN("couldn't make socket non-blocking, error %d\n", ret); WARN("couldn't make socket non-blocking, error %d\n", ret);
RPCRT4_DestroyConnection(&tcpc->common); RPCRT4_ReleaseConnection(&tcpc->common);
status = RPC_S_OUT_OF_RESOURCES; status = RPC_S_OUT_OF_RESOURCES;
continue; continue;
} }
@ -2946,6 +2946,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
} }
NewConnection = ops->alloc(); NewConnection = ops->alloc();
NewConnection->ref = 1;
NewConnection->Next = NULL; NewConnection->Next = NULL;
NewConnection->server_binding = NULL; NewConnection->server_binding = NULL;
NewConnection->server = server; NewConnection->server = server;
@ -2991,9 +2992,17 @@ static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnecti
return err; return err;
} }
RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection) RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn )
{ {
TRACE("connection: %p\n", Connection); InterlockedIncrement( &conn->ref );
return conn;
}
RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection)
{
if (InterlockedDecrement( &Connection->ref ) > 0) return RPC_S_OK;
TRACE("destroying connection %p\n", Connection);
RPCRT4_CloseConnection(Connection); RPCRT4_CloseConnection(Connection);
RPCRT4_strfree(Connection->Endpoint); RPCRT4_strfree(Connection->Endpoint);