rpcrt4: Keep a track of server context handles allocated during processing of a request.
Release them after processing of a request has finished to avoid a slow memory leak if the association isn't released for ages.
This commit is contained in:
parent
b574533e50
commit
51c051c0c4
|
@ -272,6 +272,7 @@ void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
|
|||
return; /* this is to cope with the case of the data not being valid
|
||||
* before and so not having a further reference */
|
||||
}
|
||||
RPCRT4_RemoveThreadContextHandle(SContext);
|
||||
RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, TRUE);
|
||||
}
|
||||
|
||||
|
@ -335,5 +336,6 @@ NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
|
|||
if (status != RPC_S_OK)
|
||||
RpcRaiseException(status);
|
||||
|
||||
RPCRT4_PushThreadContextHandle(SContext);
|
||||
return SContext;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define __WINE_RPC_BINDING_H
|
||||
|
||||
#include "wine/rpcss_shared.h"
|
||||
#include "rpcndr.h"
|
||||
#include "security.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
|
@ -189,5 +190,8 @@ RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t
|
|||
void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection);
|
||||
void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding);
|
||||
RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void);
|
||||
void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext);
|
||||
void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext);
|
||||
NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -172,6 +172,7 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
|
|||
void *buf = msg->Buffer;
|
||||
RPC_STATUS status;
|
||||
BOOL exception;
|
||||
NDR_SCONTEXT context_handle;
|
||||
|
||||
msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding;
|
||||
|
||||
|
@ -307,6 +308,10 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
|
|||
} __ENDTRY
|
||||
RPCRT4_SetThreadCurrentCallHandle(NULL);
|
||||
|
||||
/* release any unmarshalled context handles */
|
||||
while ((context_handle = RPCRT4_PopThreadContextHandle()) != NULL)
|
||||
RpcServerAssoc_ReleaseContextHandle(conn->server_binding->Assoc, context_handle, TRUE);
|
||||
|
||||
if (!exception)
|
||||
response = RPCRT4_BuildResponseHeader(msg->DataRepresentation,
|
||||
msg->BufferLength);
|
||||
|
|
|
@ -146,6 +146,12 @@ static CRITICAL_SECTION threaddata_cs = { &threaddata_cs_debug, -1, 0, 0, 0, 0 }
|
|||
|
||||
struct list threaddata_list = LIST_INIT(threaddata_list);
|
||||
|
||||
struct context_handle_list
|
||||
{
|
||||
struct context_handle_list *next;
|
||||
NDR_SCONTEXT context_handle;
|
||||
};
|
||||
|
||||
struct threaddata
|
||||
{
|
||||
struct list entry;
|
||||
|
@ -153,6 +159,7 @@ struct threaddata
|
|||
DWORD thread_id;
|
||||
RpcConnection *connection;
|
||||
RpcBinding *server_binding;
|
||||
struct context_handle_list *context_handle_list;
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -936,6 +943,59 @@ RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void)
|
|||
return tdata->server_binding;
|
||||
}
|
||||
|
||||
void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext)
|
||||
{
|
||||
struct threaddata *tdata = get_or_create_threaddata();
|
||||
struct context_handle_list *context_handle_list;
|
||||
|
||||
if (!tdata) return;
|
||||
|
||||
context_handle_list = HeapAlloc(GetProcessHeap(), 0, sizeof(*context_handle_list));
|
||||
if (!context_handle_list) return;
|
||||
|
||||
context_handle_list->context_handle = SContext;
|
||||
context_handle_list->next = tdata->context_handle_list;
|
||||
tdata->context_handle_list = context_handle_list;
|
||||
}
|
||||
|
||||
void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext)
|
||||
{
|
||||
struct threaddata *tdata = get_or_create_threaddata();
|
||||
struct context_handle_list *current, *prev;
|
||||
|
||||
if (!tdata) return;
|
||||
|
||||
for (current = tdata->context_handle_list, prev = NULL; current; prev = current, current = current->next)
|
||||
{
|
||||
if (current->context_handle == SContext)
|
||||
{
|
||||
if (prev)
|
||||
prev->next = current->next;
|
||||
else
|
||||
tdata->context_handle_list = current->next;
|
||||
HeapFree(GetProcessHeap(), 0, current);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void)
|
||||
{
|
||||
struct threaddata *tdata = get_or_create_threaddata();
|
||||
struct context_handle_list *context_handle_list;
|
||||
NDR_SCONTEXT context_handle;
|
||||
|
||||
if (!tdata) return NULL;
|
||||
|
||||
context_handle_list = tdata->context_handle_list;
|
||||
if (!context_handle_list) return NULL;
|
||||
tdata->context_handle_list = context_handle_list->next;
|
||||
|
||||
context_handle = context_handle_list->context_handle;
|
||||
HeapFree(GetProcessHeap(), 0, context_handle_list);
|
||||
return context_handle;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* RpcCancelThread (rpcrt4.@)
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue