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