Rob Shearman : rpcrt4: Keep a track of server context handles allocated during processing of a request .
Alexandre Julliard
julliard at winehq.org
Mon Dec 31 12:32:24 CST 2007
Module: wine
Branch: master
Commit: 51c051c0c4fc26e45ab6c04684acf73886eeb7a1
URL: http://source.winehq.org/git/wine.git/?a=commit;h=51c051c0c4fc26e45ab6c04684acf73886eeb7a1
Author: Rob Shearman <rob at codeweavers.com>
Date: Sun Dec 30 16:44:54 2007 +0000
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.
---
dlls/rpcrt4/ndr_contexthandle.c | 2 +
dlls/rpcrt4/rpc_binding.h | 4 ++
dlls/rpcrt4/rpc_server.c | 5 +++
dlls/rpcrt4/rpcrt4_main.c | 60 +++++++++++++++++++++++++++++++++++++++
4 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/dlls/rpcrt4/ndr_contexthandle.c b/dlls/rpcrt4/ndr_contexthandle.c
index 0b3eeb1..7b3c3fd 100644
--- a/dlls/rpcrt4/ndr_contexthandle.c
+++ b/dlls/rpcrt4/ndr_contexthandle.c
@@ -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;
}
diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h
index b774074..ed8d4ea 100644
--- a/dlls/rpcrt4/rpc_binding.h
+++ b/dlls/rpcrt4/rpc_binding.h
@@ -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
diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c
index a1262da..34c71c7 100644
--- a/dlls/rpcrt4/rpc_server.c
+++ b/dlls/rpcrt4/rpc_server.c
@@ -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);
diff --git a/dlls/rpcrt4/rpcrt4_main.c b/dlls/rpcrt4/rpcrt4_main.c
index 887e049..e48cf58 100644
--- a/dlls/rpcrt4/rpcrt4_main.c
+++ b/dlls/rpcrt4/rpcrt4_main.c
@@ -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.@)
*/
More information about the wine-cvs
mailing list