dbus/mono Arguments.cs, 1.9, 1.10 Bus.cs, 1.1, 1.2 Connection.cs, 1.12, 1.13 Handler.cs, 1.7, 1.8 Message.cs, 1.10, 1.11 ProxyBuilder.cs, 1.5, 1.6 Service.cs, 1.10, 1.11

Joe Shaw joe at freedesktop.org
Tue Mar 8 20:36:17 PST 2005


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

Modified Files:
	Arguments.cs Bus.cs Connection.cs Handler.cs Message.cs 
	ProxyBuilder.cs Service.cs 
Log Message:
2005-03-08  Joe Shaw  <joeshaw at novell.com>

	Fix a bunch of lifecycle and memory management problems
	in the mono bindings.

	* mono/Arguments.cs (Arguments): Implement IDisposable

	* mono/Bus.cs (Bus): Don't allow public instantiation.  This is
	strictly a static class.

	* mono/Connection.cs: Move the DBusObjectPathVTable and associated
	delegates into this file.
	(Connection): Implement IDisposable.
	(Dispose): Disconnect the connection and set the raw connection
	pointer to IntPtr.Zero.
	(~Connection): Call Dispose().
	(RegisterObjectPath): Added.  Manages the registration of object
	paths so we can cleanly disconnect them at dispose/finalize time.
	(UnregisterObjectPath): Ditto.
	(set_RawConnection): Unregister all of the object paths when
	changing the underlying DBusConnection.  Add them back onto the
	new connection, if any.

	* mono/Handler.cs: Don't implement IDisposable; it doesn't use any
	more unmanaged resources anymore, so it's not necessary.  Move all
	the DBusObjectPathVTable stuff out of here.
	(Handler): Save references to our delegates so that they don't get
	finalized.  Call Connection.RegisterObjectPath() instead of
	dbus_connection_register_object_path() directly.
	(Message_Called): Dispose the message after we're finished with
	it.

	* mono/Message.cs (Message): Implement IDisposable.
	(Dispose): Dispose the Arguments, and set the RawMessage to
	IntPtr.Zero.
	(SendWithReplyAndBlock): We own the ref to the reply that comes
	back from dbus_connection_send_with_reply_and_block() so add a
	comment about that and unref it after we've constructed a managed
	MethodReturn class around it.  Fixes a big, big leak.

	* mono/ProxyBuilder.cs: Reflect into Message to get the Dispose
	method.
	(BuildSignalHandler): After we've sent the Signal message, dispose
	of it.
	(BuildMethod): Dispose of the method call and reply messages after
	we've sent the message and extracted the data we want from the
	reply.

	* mono/Service.cs (UnregisterObject): Don't call handler.Dispose()
	anymore.
	(Service_FilterCalled): Dispose of the message after we're
	finished with it.

Index: Arguments.cs
===================================================================
RCS file: /cvs/dbus/dbus/mono/Arguments.cs,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- Arguments.cs	25 Jan 2005 19:47:13 -0000	1.9
+++ Arguments.cs	9 Mar 2005 04:36:15 -0000	1.10
@@ -7,29 +7,37 @@
 {
   // Holds the arguments of a message. Provides methods for appending
   // arguments and to assist in matching .NET types with D-BUS types.
-  public class Arguments : IEnumerable
+	public class Arguments : IEnumerable, IDisposable
   {
     // Must follow sizeof(DBusMessageIter)
     internal const int DBusMessageIterSize = 14*4;
     private static Hashtable dbusTypes = null;
     private Message message;
-    private IntPtr appenderIter = Marshal.AllocCoTaskMem(DBusMessageIterSize);
+    private IntPtr appenderIter;
     private IEnumerator enumerator = null;
     
-    internal Arguments()
+    internal Arguments (Message message)
     {
+      this.appenderIter = Marshal.AllocCoTaskMem(DBusMessageIterSize);
+      this.message = message;
     }
 
-    ~Arguments()
+    private void Dispose (bool disposing)
     {
       Marshal.FreeCoTaskMem(appenderIter);
     }
 
-    internal Arguments(Message message)
+    public void Dispose ()
     {
-      this.message = message;
+      Dispose (true);
+      GC.SuppressFinalize (this);
     }
-    
+
+    ~Arguments()
+    {
+      Dispose (false);
+    }
+
     // Checks the suitability of a D-BUS type for supporting a .NET
     // type.
     public static bool Suits(Type dbusType, Type type) 

Index: Bus.cs
===================================================================
RCS file: /cvs/dbus/dbus/mono/Bus.cs,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Bus.cs	23 Mar 2004 12:10:32 -0000	1.1
+++ Bus.cs	9 Mar 2005 04:36:15 -0000	1.2
@@ -14,6 +14,9 @@
       Activation = 2
     }
 
+    // Don't allow instantiation
+    private Bus () { }
+
     public static Connection GetSessionBus() 
     {
       return GetBus(BusType.Session);

Index: Connection.cs
===================================================================
RCS file: /cvs/dbus/dbus/mono/Connection.cs,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- Connection.cs	8 Mar 2005 20:45:03 -0000	1.12
+++ Connection.cs	9 Mar 2005 04:36:15 -0000	1.13
@@ -12,7 +12,36 @@
 						 IntPtr rawMessage,
 						 IntPtr userData);
 
-  public class Connection 
+  internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
+							  IntPtr userData);
+
+  internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection,
+						      IntPtr rawMessage,
+						      IntPtr userData);
+
+  [StructLayout (LayoutKind.Sequential)]
+  internal struct DBusObjectPathVTable
+  {
+    public DBusObjectPathUnregisterFunction unregisterFunction;
+    public DBusObjectPathMessageFunction messageFunction;
+    public IntPtr padding1;
+    public IntPtr padding2;
+    public IntPtr padding3;
+    public IntPtr padding4;
+    
+    public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction,
+				DBusObjectPathMessageFunction messageFunction) 
+    {
+      this.unregisterFunction = unregisterFunction;
+      this.messageFunction = messageFunction;
+      this.padding1 = IntPtr.Zero;
+      this.padding2 = IntPtr.Zero;
+      this.padding3 = IntPtr.Zero;
+      this.padding4 = IntPtr.Zero;
+    }
+  }
+
+  public class Connection : IDisposable
   {
     /// <summary>
     /// A pointer to the underlying Connection structure
@@ -26,8 +55,9 @@
     
     private int timeout = -1;
 
-    private ArrayList filters = new ArrayList (); // of DBusHandleMessageFunction
-    private ArrayList matches = new ArrayList (); // of string
+    private ArrayList filters = new ArrayList ();      // of DBusHandleMessageFunction
+    private ArrayList matches = new ArrayList ();      // of string
+    private Hashtable object_paths = new Hashtable (); // key: string  value: DBusObjectPathVTable
 
     internal Connection(IntPtr rawConnection)
     {
@@ -49,6 +79,22 @@
       SetupWithMain();
     }
 
+    public void Dispose() 
+    {
+      Dispose(true);
+      GC.SuppressFinalize(this);
+    }
+    
+    public void Dispose (bool disposing) 
+    {
+      if (disposing && RawConnection != IntPtr.Zero) 
+	{
+	  dbus_connection_disconnect(rawConnection);
+
+	  RawConnection = IntPtr.Zero; // free the native object
+	}
+    }
+
     public void Flush()
     {
       dbus_connection_flush(RawConnection);
@@ -61,17 +107,7 @@
     
     ~Connection () 
     {
-      if (RawConnection != IntPtr.Zero) 
-	{
-          foreach (DBusHandleMessageFunction func in this.filters)
-            RemoveFilter (func);
-
-          foreach (string match_rule in this.matches)
-            RemoveMatch (match_rule);
-
-	  dbus_connection_disconnect(rawConnection);
-	}
-      RawConnection = IntPtr.Zero; // free the native object
+      Dispose (false);
     }
     
     internal static Connection Wrap(IntPtr rawConnection) 
@@ -121,6 +157,22 @@
       this.matches.Remove (match_rule);
     }
 
+    internal void RegisterObjectPath (string path, DBusObjectPathVTable vtable)
+    {
+      if (!dbus_connection_register_object_path (RawConnection, path, ref vtable, IntPtr.Zero))
+        throw new OutOfMemoryException ();
+ 
+      this.object_paths[path] = vtable;
+    }
+ 
+    internal void UnregisterObjectPath (string path)
+    {
+      dbus_connection_unregister_object_path (RawConnection, path);
+ 
+      this.object_paths.Remove (path);
+    }
+
+
     public string UniqueName
     {
       get
@@ -178,6 +230,9 @@
               foreach (string match_rule in this.matches)
                 dbus_bus_remove_match (rawConnection, match_rule, IntPtr.Zero);
 
+              foreach (string path in this.object_paths.Keys)
+                dbus_connection_unregister_object_path (rawConnection, path);
+
 	      // Get the reference to this
 	      IntPtr rawThis = dbus_connection_get_data (rawConnection, Slot);
 	      Debug.Assert (rawThis != IntPtr.Zero);
@@ -211,11 +266,17 @@
 
               foreach (string match_rule in this.matches)
                 dbus_bus_add_match (rawConnection, match_rule, IntPtr.Zero);
+
+              foreach (string path in this.object_paths.Keys) {
+                DBusObjectPathVTable vtable = (DBusObjectPathVTable) this.object_paths[path];
+                dbus_connection_register_object_path (rawConnection, path, ref vtable, IntPtr.Zero);
+	      }
 	    }
 	  else
 	    {
 	      this.filters.Clear ();
               this.matches.Clear ();
+	      this.object_paths.Clear ();
 	    }
 	}
     }
@@ -278,5 +339,16 @@
     private extern static void dbus_bus_remove_match(IntPtr rawConnection,
 						     string rule,
 						     IntPtr erro);
+
+    [DllImport ("dbus-1")]
+    private extern static bool dbus_connection_register_object_path (IntPtr rawConnection,
+								     string path,
+								     ref DBusObjectPathVTable vTable,
+								     IntPtr userData);
+
+    [DllImport ("dbus-1")]
+    private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection,
+								       string path);
+
   }
 }

Index: Handler.cs
===================================================================
RCS file: /cvs/dbus/dbus/mono/Handler.cs,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- Handler.cs	31 Aug 2004 03:59:14 -0000	1.7
+++ Handler.cs	9 Mar 2005 04:36:15 -0000	1.8
@@ -13,7 +13,7 @@
     NeedMemory = 2
   }
 
-  internal class Handler : IDisposable
+  internal class Handler
   {
     private string path = null;
     private Introspector introspector = null;
@@ -21,70 +21,12 @@
     private DBusObjectPathVTable vTable;
     private Connection connection;
     private Service service;
-    private bool disposed = false;
-    
-    internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
-							    IntPtr userData);
-
-    internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection,
-							IntPtr rawMessage,
-							IntPtr userData);
-
-    [StructLayout (LayoutKind.Sequential)]
-    private struct DBusObjectPathVTable 
-    {
-      public DBusObjectPathUnregisterFunction unregisterFunction;
-      public DBusObjectPathMessageFunction messageFunction;
-      public IntPtr padding1;
-      public IntPtr padding2;
-      public IntPtr padding3;
-      public IntPtr padding4;
-    
-      public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction,
-				  DBusObjectPathMessageFunction messageFunction) 
-      {
-	this.unregisterFunction = unregisterFunction;
-	this.messageFunction = messageFunction;
-	this.padding1 = IntPtr.Zero;
-	this.padding2 = IntPtr.Zero;
-	this.padding3 = IntPtr.Zero;
-	this.padding4 = IntPtr.Zero;
-      }
-    }
-
-    public void Dispose() 
-    {
-      Dispose(true);
-      GC.SuppressFinalize(this);
-    }
-    
-    private void Dispose(bool disposing) 
-    {
-      if (!disposed) {	
-	if (disposing) {
-	  // Clean up managed resources
-	}
-
-	service = null;
-
-	// Clean up unmanaged resources
-	if (Connection != null && Connection.RawConnection != IntPtr.Zero && Path != null) {
-	  dbus_connection_unregister_object_path(Connection.RawConnection,
-						 Path);
-	}	
 
-	connection = null;
-	introspector = null;
-	handledObject = null;
-      }
-      
-      disposed = true;    
-    }
-
-    ~Handler() 
-    {
-      Dispose(false);
-    }
+    // We need to hold extra references to these callbacks so that they don't
+    // get garbage collected before they are called back into from unmanaged
+    // code.
+    private DBusObjectPathUnregisterFunction unregister_func;
+    private DBusObjectPathMessageFunction message_func;
 
     public Handler(object handledObject, 
 		   string path, 
@@ -96,15 +38,11 @@
       this.path = path;
       
       // Create the vTable and register the path
-      vTable = new DBusObjectPathVTable(new DBusObjectPathUnregisterFunction(Unregister_Called), 
-					new DBusObjectPathMessageFunction(Message_Called));
-      
-      if (!dbus_connection_register_object_path(Connection.RawConnection,
-						Path,
-						ref vTable,
-						IntPtr.Zero))
-	throw new OutOfMemoryException();
+      this.unregister_func = new DBusObjectPathUnregisterFunction (Unregister_Called);
+      this.message_func = new DBusObjectPathMessageFunction (Message_Called);
 
+      vTable = new DBusObjectPathVTable (this.unregister_func, this.message_func);
+      Connection.RegisterObjectPath (Path, vTable);
       RegisterSignalHandlers();
     }
 
@@ -131,8 +69,6 @@
       set {
 	this.handledObject = value;
 	
-	object[] attributes;
-	
 	// Register the methods
 	this.introspector = Introspector.GetIntrospector(value.GetType());	  
       }
@@ -153,17 +89,22 @@
 			       IntPtr userData) 
     {
       Message message = Message.Wrap(rawMessage, Service);
+      Result res = Result.NotYetHandled;
 
       switch (message.Type) {
+      case Message.MessageType.MethodCall:
+        res = HandleMethod ((MethodCall) message);
+	break;
+
       case Message.MessageType.Signal:
 	// We're not interested in signals here because we're the ones
 	// that generate them!
 	break;
-      case Message.MessageType.MethodCall:
-	return (int) HandleMethod((MethodCall) message);
       }
 
-      return (int) Result.NotYetHandled;
+      message.Dispose ();
+
+      return (int) res;
     }
     
     private Result HandleMethod(MethodCall methodCall)
@@ -227,12 +168,5 @@
 	  this.service = value;
 	}
     }
-
-    [DllImport ("dbus-1")]
-    private extern static bool dbus_connection_register_object_path (IntPtr rawConnection, string path, ref DBusObjectPathVTable vTable, IntPtr userData);
-
-    [DllImport ("dbus-1")]
-    private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection, string path);
-
   }
 }

Index: Message.cs
===================================================================
RCS file: /cvs/dbus/dbus/mono/Message.cs,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- Message.cs	31 Aug 2004 03:59:14 -0000	1.10
+++ Message.cs	9 Mar 2005 04:36:15 -0000	1.11
@@ -6,7 +6,7 @@
   using System.Diagnostics;
   using System.Collections;
   
-  public class Message 
+  public class Message : IDisposable
   {
     private static Stack stack = new Stack ();
 	  
@@ -83,10 +83,26 @@
     {
       this.service = service;
     }
+
+    public void Dispose() 
+    {
+      Dispose(true);
+      GC.SuppressFinalize(this);
+    }
     
-    ~Message() 
+    public void Dispose (bool disposing) 
     {
+      if (disposing) {
+        if (this.arguments != null)
+	  this.arguments.Dispose ();
+      }
+
       RawMessage = IntPtr.Zero; // free the native object
+    }     
+
+    ~Message() 
+    {
+      Dispose (false);
     }
     
     public static Message Wrap(IntPtr rawMessage, Service service) 
@@ -198,6 +214,12 @@
 
       if (rawMessage != IntPtr.Zero) {
 	MethodReturn methodReturn = new MethodReturn(rawMessage, Service);
+	// Ownership of a ref is passed onto us from
+	// dbus_connection_send_with_reply_and_block().  It gets reffed as
+	// a result of being passed into the MethodReturn ctor, so unref
+	// the extra one here.
+	dbus_message_unref (rawMessage);
+
 	return methodReturn;
       } else {
 	throw new DBusException(error);

Index: ProxyBuilder.cs
===================================================================
RCS file: /cvs/dbus/dbus/mono/ProxyBuilder.cs,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ProxyBuilder.cs	26 Mar 2004 15:25:59 -0000	1.5
+++ ProxyBuilder.cs	9 Mar 2005 04:36:15 -0000	1.6
@@ -35,6 +35,8 @@
 											     new Type[0]);
     private static MethodInfo Message_SendMI = typeof(Message).GetMethod("Send",
 									 new Type[0]);
+    private static MethodInfo Message_DisposeMI = typeof(Message).GetMethod("Dispose",
+									    new Type[0]);
     private static MethodInfo Arguments_GetEnumeratorMI = typeof(Arguments).GetMethod("GetEnumerator",
 											  new Type[0]);
     private static MethodInfo IEnumerator_MoveNextMI = typeof(System.Collections.IEnumerator).GetMethod("MoveNext",
@@ -197,7 +199,6 @@
       // Generate the locals
       LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
       methodCallL.SetLocalSymInfo("signal");
-      LocalBuilder replyL = generator.DeclareLocal(typeof(MethodReturn));
 
       //generator.EmitWriteLine("Signal signal = new Signal(...)");
       generator.Emit(OpCodes.Ldsfld, serviceF);
@@ -224,6 +225,10 @@
       generator.Emit(OpCodes.Ldloc_0);
       generator.EmitCall(OpCodes.Callvirt, Message_SendMI, null); 
 
+      //generator.EmitWriteLine("signal.Dispose()");
+      generator.Emit(OpCodes.Ldloc_0);
+      generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
+
       //generator.EmitWriteLine("return");
       generator.Emit(OpCodes.Ret);
     }
@@ -310,6 +315,15 @@
 	}
       }
 
+      // Clean up after ourselves
+      //generator.EmitWriteLine("methodCall.Dispose()");
+      generator.Emit(OpCodes.Ldloc_0);
+      generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
+
+      //generator.EmitWriteLine("reply.Dispose()");
+      generator.Emit(OpCodes.Ldloc_1);
+      generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
+
       if (method.ReturnType != typeof(void)) {
 	generator.Emit(OpCodes.Ldloc_3);
       }

Index: Service.cs
===================================================================
RCS file: /cvs/dbus/dbus/mono/Service.cs,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- Service.cs	12 Feb 2005 00:51:33 -0000	1.10
+++ Service.cs	9 Mar 2005 04:36:15 -0000	1.11
@@ -75,9 +75,7 @@
 
     public void UnregisterObject(object handledObject) 
     {
-      Handler handler = (Handler) registeredHandlers[handledObject];
       registeredHandlers.Remove(handledObject);
-      handler.Dispose();
     }
 
     public void RegisterObject(object handledObject, 
@@ -128,6 +126,8 @@
 	}
       }
       
+      message.Dispose ();
+
       return (int) Result.NotYetHandled;
     }
 



More information about the dbus-commit mailing list