dbus/mono ProxyBuilder.cs,1.5.2.1,1.5.2.2

Joe Shaw joe at freedesktop.org
Sat Mar 12 17:12:02 PST 2005


Update of /cvs/dbus/dbus/mono
In directory gabe:/tmp/cvs-serv9650/mono

Modified Files:
      Tag: dbus-0-23
	ProxyBuilder.cs 
Log Message:
2005-03-12  Joe Shaw  <joeshaw at novell.com>

	* mono/ProxyBuilder.cs: Add a finalizer to the generated proxy
	classes that disconnects the signal handler delegate from the
	service object.  Fixes a big leak of proxy objects on the
	client side of things.  Patch from Ben Maurer
	<bmaurer at ximian.com>

Index: ProxyBuilder.cs
===================================================================
RCS file: /cvs/dbus/dbus/mono/ProxyBuilder.cs,v
retrieving revision 1.5.2.1
retrieving revision 1.5.2.2
diff -u -d -r1.5.2.1 -r1.5.2.2
--- ProxyBuilder.cs	9 Mar 2005 04:35:17 -0000	1.5.2.1
+++ ProxyBuilder.cs	13 Mar 2005 01:11:59 -0000	1.5.2.2
@@ -21,6 +21,8 @@
 										  new Type[0]);
     private static MethodInfo Service_AddSignalCalledMI = typeof(Service).GetMethod("add_SignalCalled",
 										    new Type[] {typeof(Service.SignalCalledHandler)});
+    private static MethodInfo Service_RemoveSignalCalledMI = typeof(Service).GetMethod("remove_SignalCalled",
+										    new Type[] {typeof(Service.SignalCalledHandler)});										    
     private static MethodInfo Signal_PathNameMI = typeof(Signal).GetMethod("get_PathName",
 									   new Type[0]);
     private static MethodInfo Message_ArgumentsMI = typeof(Message).GetMethod("get_Arguments",
@@ -402,7 +404,7 @@
       }
     }
     
-    public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF, MethodInfo signalCalledMI)
+    public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF, MethodInfo signalCalledMI, FieldInfo deleF)
     {
       Type[] pars = {typeof(Service), typeof(string)};
       ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName | 
@@ -419,12 +421,19 @@
       generator.Emit(OpCodes.Ldarg_0);
       generator.Emit(OpCodes.Ldarg_2);
       generator.Emit(OpCodes.Stfld, pathF);
-      
-      //generator.EmitWriteLine("myService.SignalCalled += new Service.SignalCalledHandler(Service_SignalCalled)");
+
+      //generator.EmitWriteLine("this.delegate_created = new Service.SignalCalledHandler(Service_SignalCalled)");      
       generator.Emit(OpCodes.Ldarg_1);
       generator.Emit(OpCodes.Ldarg_0);
       generator.Emit(OpCodes.Ldftn, signalCalledMI);
       generator.Emit(OpCodes.Newobj, Service_SignalCalledHandlerC);
+      generator.Emit(OpCodes.Stloc_0);
+      generator.Emit(OpCodes.Ldarg_0);
+      generator.Emit(OpCodes.Ldloc_0);
+      generator.Emit(OpCodes.Stfld, deleF);
+
+      //generator.EmitWriteLine("myService.SignalCalled += this.delegate_created");
+      generator.Emit(OpCodes.Ldloc_0);
       generator.EmitCall(OpCodes.Callvirt, Service_AddSignalCalledMI, null);
 
       //generator.EmitWriteLine("return");
@@ -453,6 +462,27 @@
       generator.Emit(OpCodes.Ret);
     }
     
+    public void BuildFinalizer (TypeBuilder tb, FieldInfo fi)
+    {
+       // Note that this is a *HORRIBLE* example of how to build a finalizer
+       // It doesn't use the try/finally to chain to Object::Finalize. However,
+       // because that is always going to be a nop, lets just ignore that here.
+       // If you are trying to find the right code, look at what mcs does ;-).
+
+       MethodBuilder mb = tb.DefineMethod("Finalize", 
+					  MethodAttributes.Family |
+					  MethodAttributes.HideBySig |
+					  MethodAttributes.Virtual, 
+					  typeof (void), 
+					  new Type [0]);
+       ILGenerator generator = mb.GetILGenerator();
+
+       //generator.EmitWriteLine("this.service.SignalCalled -= this.delegate_created");
+       generator.Emit (OpCodes.Ldfld, fi);
+       generator.Emit (OpCodes.Call, Service_RemoveSignalCalledMI);
+       generator.Emit (OpCodes.Ret);
+    }
+    
     public object GetSignalProxy()
     {
       Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".SignalProxy");
@@ -516,9 +546,13 @@
 	FieldBuilder pathF = typeB.DefineField("pathName", 
 					       typeof(string), 
 					       FieldAttributes.Private);
+	FieldBuilder deleF = typeB.DefineField("delegate_created", 
+					       typeof(Service.SignalCalledHandler), 
+					       FieldAttributes.Private);
+	BuildFinalizer (typeB, deleF);
 	
 	MethodInfo signalCalledMI = BuildSignalCalled(ref typeB, serviceF, pathF);
-	BuildConstructor(ref typeB, serviceF, pathF, signalCalledMI);
+	BuildConstructor(ref typeB, serviceF, pathF, signalCalledMI, deleF);
 	
 	// Build the methods
 	foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {



More information about the dbus-commit mailing list