diff options
author | Joe Shaw <joeshaw@novell.com> | 2005-03-09 04:36:15 +0000 |
---|---|---|
committer | Joe Shaw <joeshaw@novell.com> | 2005-03-09 04:36:15 +0000 |
commit | 2958e723fc996e2dd7edfdc6ac53dcdf48323549 (patch) | |
tree | c031fe0f0f40e868f18eb3e257667856c1d9f4fc /mono/Connection.cs | |
parent | d96c9e465abb291cb943a1b4ec3643de4b3f6423 (diff) |
2005-03-08 Joe Shaw <joeshaw@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.
Diffstat (limited to 'mono/Connection.cs')
-rw-r--r-- | mono/Connection.cs | 100 |
1 files changed, 86 insertions, 14 deletions
diff --git a/mono/Connection.cs b/mono/Connection.cs index 6abd7e80..af0764db 100644 --- a/mono/Connection.cs +++ b/mono/Connection.cs @@ -12,7 +12,36 @@ namespace DBus 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 @@ namespace DBus 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 @@ namespace DBus 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 @@ namespace DBus ~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 @@ namespace DBus 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 @@ namespace DBus 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 @@ namespace DBus 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 @@ namespace DBus 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); + } } |