From baf383d1b14ebcd217a587fe8c78202fc5e9193b Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Wed, 14 Jul 2010 14:46:12 -0400 Subject: [PATCH] GDBusConnection: copy object and subtree virtual tables Signed-off-by: David Zeuthen --- gio/gdbusconnection.c | 58 ++++++++++++++++++++++++++++++++++++------- gio/gdbusconnection.h | 19 +++++++------- 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c index 7290e2005..389dc2942 100644 --- a/gio/gdbusconnection.c +++ b/gio/gdbusconnection.c @@ -3391,6 +3391,40 @@ purge_all_signal_subscriptions (GDBusConnection *connection) /* ---------------------------------------------------------------------------------------------------- */ +static GDBusInterfaceVTable * +_g_dbus_interface_vtable_copy (const GDBusInterfaceVTable *vtable) +{ + /* Don't waste memory by copying padding - remember to update this + * when changing struct _GDBusInterfaceVTable in gdbusconnection.h + */ + return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); +} + +static void +_g_dbus_interface_vtable_free (GDBusInterfaceVTable *vtable) +{ + g_free (vtable); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static GDBusSubtreeVTable * +_g_dbus_subtree_vtable_copy (const GDBusSubtreeVTable *vtable) +{ + /* Don't waste memory by copying padding - remember to update this + * when changing struct _GDBusSubtreeVTable in gdbusconnection.h + */ + return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); +} + +static void +_g_dbus_subtree_vtable_free (GDBusSubtreeVTable *vtable) +{ + g_free (vtable); +} + +/* ---------------------------------------------------------------------------------------------------- */ + struct ExportedObject { gchar *object_path; @@ -3415,8 +3449,8 @@ typedef struct guint id; gchar *interface_name; - const GDBusInterfaceVTable *vtable; - const GDBusInterfaceInfo *interface_info; + GDBusInterfaceVTable *vtable; + GDBusInterfaceInfo *interface_info; GMainContext *context; gpointer user_data; @@ -3437,6 +3471,7 @@ exported_interface_free (ExportedInterface *ei) g_main_context_unref (ei->context); g_free (ei->interface_name); + _g_dbus_interface_vtable_free (ei->vtable); g_free (ei); } @@ -4413,10 +4448,6 @@ obj_message_func (GDBusConnection *connection, * If an existing callback is already registered at @object_path and * @interface_name, then @error is set to #G_IO_ERROR_EXISTS. * - * Note that @vtable is not copied, so the struct you pass must exist until - * the path is unregistered. One possibility is to free @vtable at the - * same time as @user_data when @user_data_free_func is called. - * * GDBus automatically implements the standard D-Bus interfaces * org.freedesktop.DBus.Properties, org.freedesktop.DBus.Introspectable * and org.freedesktop.Peer, so you don't have to implement those for @@ -4424,6 +4455,11 @@ obj_message_func (GDBusConnection *connection, * org.freedesktop.DBus.Properties yourself, e.g. to handle getting * and setting of properties asynchronously. * + * Note that the reference count on @interface_info will be + * incremented by 1 (unless allocated statically, e.g. if the + * reference count is -1, see g_dbus_interface_info_ref()) for as long + * as the object is exported. Also note that @vtable will be copied. + * * See for an example of how to use this method. * * Returns: 0 if @error is set, otherwise a registration id (never 0) @@ -4484,7 +4520,7 @@ g_dbus_connection_register_object (GDBusConnection *connection, ei->eo = eo; ei->user_data = user_data; ei->user_data_free_func = user_data_free_func; - ei->vtable = vtable; + ei->vtable = _g_dbus_interface_vtable_copy (vtable); ei->interface_info = g_dbus_interface_info_ref ((GDBusInterfaceInfo *) interface_info); ei->interface_name = g_strdup (interface_info->name); ei->context = g_main_context_get_thread_default (); @@ -5094,7 +5130,7 @@ struct ExportedSubtree guint id; gchar *object_path; GDBusConnection *connection; - const GDBusSubtreeVTable *vtable; + GDBusSubtreeVTable *vtable; GDBusSubtreeFlags flags; GMainContext *context; @@ -5112,6 +5148,7 @@ exported_subtree_free (ExportedSubtree *es) if (es->context != NULL) g_main_context_unref (es->context); + _g_dbus_subtree_vtable_free (es->vtable); g_free (es->object_path); g_free (es); } @@ -5532,6 +5569,9 @@ subtree_message_func (GDBusConnection *connection, * for object paths not registered via g_dbus_connection_register_object() * or other bindings. * + * Note that @vtable will be copied so you cannot change it after + * registration. + * * See for an example of how to use this method. * * Returns: 0 if @error is set, otherwise a subtree registration id (never 0) @@ -5575,7 +5615,7 @@ g_dbus_connection_register_subtree (GDBusConnection *connection, es->object_path = g_strdup (object_path); es->connection = connection; - es->vtable = vtable; + es->vtable = _g_dbus_subtree_vtable_copy (vtable); es->flags = flags; es->id = _global_subtree_registration_id++; /* TODO: overflow etc. */ es->user_data = user_data; diff --git a/gio/gdbusconnection.h b/gio/gdbusconnection.h index 6dfb6fbbd..3a1ff4690 100644 --- a/gio/gdbusconnection.h +++ b/gio/gdbusconnection.h @@ -278,7 +278,10 @@ struct _GDBusInterfaceVTable GDBusInterfaceSetPropertyFunc set_property; /*< private >*/ - /* Padding for future expansion */ + /* Padding for future expansion - also remember to update + * gdbusconnection.c:_g_dbus_interface_vtable_copy() when + * changing this. + */ gpointer padding[8]; }; @@ -374,15 +377,11 @@ struct _GDBusSubtreeVTable GDBusSubtreeDispatchFunc dispatch; /*< private >*/ - /* Padding for future expansion */ - void (*_g_reserved1) (void); - void (*_g_reserved2) (void); - void (*_g_reserved3) (void); - void (*_g_reserved4) (void); - void (*_g_reserved5) (void); - void (*_g_reserved6) (void); - void (*_g_reserved7) (void); - void (*_g_reserved8) (void); + /* Padding for future expansion - also remember to update + * gdbusconnection.c:_g_dbus_subtree_vtable_copy() when + * changing this. + */ + gpointer padding[8]; }; guint g_dbus_connection_register_subtree (GDBusConnection *connection,