diff options
author | Alexander Larsson <alexl@redhat.com> | 2008-09-23 19:16:06 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2008-09-23 19:16:06 +0000 |
commit | 0d1cff0829a4a1f4ce1095d9da694dcaaa74f024 (patch) | |
tree | 145acf6acb21ab39e0bc43deab47b365ec781156 | |
parent | cc32fbdb7b1b52d7d28f31a4e967a99438ad68db (diff) | |
download | gvfs-0d1cff0829a4a1f4ce1095d9da694dcaaa74f024.tar.gz |
Only call the IsSupported dbus call when the class is actually needed
2008-09-23 Alexander Larsson <alexl@redhat.com>
* monitor/proxy/gproxyvolumemonitor.[ch]:
* monitor/proxy/gproxyvolumemonitor.h:
* monitor/proxy/remote-volume-monitor-module.c:
Only call the IsSupported dbus call when the class
is actually needed instead of on gio init.
Don't integrate internal session bus with mainloop
during is_support code, as that is not necessary yet, and
it caused problem if done in a thread.
This fixes the trash crash issue in bug #547568.
2008-09-23 Alexander Larsson <alexl@redhat.com>
* client/Makefile.am:
* common/Makefile.am:
* common/gmountsource.c:
* common/gmounttracker.c:
* monitor/gphoto2/Makefile.am:
* monitor/hal/Makefile.am:
* monitor/proxy/Makefile.am:
Link all modules against the installed libgvfscommon instead
of duplicating the statically linked one. This is safe wrt
namespace conflicts, because the modules are opened RTLD_LOCAL
so the dependencies will not pollute the global namespace.
* client/gdaemonvfs.c:
Make the gvfsdbus module persistant. This means we will never
unload it, and thus not unload libgvfscommon which could
be problematic. This is not a huge problem, as:
+ The gio modules will not be loaded anyway unless you use gio
+ The gvfsdbus module will be persistent anyway as soon as
the app references the GVfs object, which likely all gio apps do
+ The module load order doesn't matter wrt unload order, because
all gio modules are loaded before any one is unloaded.
svn path=/trunk/; revision=2021
-rw-r--r-- | ChangeLog | 37 | ||||
-rw-r--r-- | client/Makefile.am | 2 | ||||
-rw-r--r-- | client/gdaemonvfs.c | 8 | ||||
-rw-r--r-- | common/Makefile.am | 8 | ||||
-rw-r--r-- | common/gmountsource.c | 25 | ||||
-rw-r--r-- | common/gmounttracker.c | 26 | ||||
-rw-r--r-- | monitor/gphoto2/Makefile.am | 2 | ||||
-rw-r--r-- | monitor/hal/Makefile.am | 2 | ||||
-rw-r--r-- | monitor/proxy/Makefile.am | 4 | ||||
-rw-r--r-- | monitor/proxy/gproxyvolumemonitor.c | 221 | ||||
-rw-r--r-- | monitor/proxy/gproxyvolumemonitor.h | 3 | ||||
-rw-r--r-- | monitor/proxy/remote-volume-monitor-module.c | 3 |
12 files changed, 186 insertions, 155 deletions
@@ -1,3 +1,40 @@ +2008-09-23 Alexander Larsson <alexl@redhat.com> + + * monitor/proxy/gproxyvolumemonitor.[ch]: + * monitor/proxy/gproxyvolumemonitor.h: + * monitor/proxy/remote-volume-monitor-module.c: + Only call the IsSupported dbus call when the class + is actually needed instead of on gio init. + Don't integrate internal session bus with mainloop + during is_support code, as that is not necessary yet, and + it caused problem if done in a thread. + + This fixes the trash crash issue in bug #547568. + +2008-09-23 Alexander Larsson <alexl@redhat.com> + + * client/Makefile.am: + * common/Makefile.am: + * common/gmountsource.c: + * common/gmounttracker.c: + * monitor/gphoto2/Makefile.am: + * monitor/hal/Makefile.am: + * monitor/proxy/Makefile.am: + Link all modules against the installed libgvfscommon instead + of duplicating the statically linked one. This is safe wrt + namespace conflicts, because the modules are opened RTLD_LOCAL + so the dependencies will not pollute the global namespace. + + * client/gdaemonvfs.c: + Make the gvfsdbus module persistant. This means we will never + unload it, and thus not unload libgvfscommon which could + be problematic. This is not a huge problem, as: + + The gio modules will not be loaded anyway unless you use gio + + The gvfsdbus module will be persistent anyway as soon as + the app references the GVfs object, which likely all gio apps do + + The module load order doesn't matter wrt unload order, because + all gio modules are loaded before any one is unloaded. + 2008-09-16 Tomas Bzatek <tbzatek@redhat.com> * daemon/gvfsbackendsmb.c: diff --git a/client/Makefile.am b/client/Makefile.am index 9d61e204..274d9fd3 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -39,7 +39,7 @@ vfssources = \ $(NULL) vfslibs = \ - $(top_builddir)/common/libgvfscommon-noin.la \ + $(top_builddir)/common/libgvfscommon.la \ $(DBUS_LIBS) \ $(GLIB_LIBS) \ $(NULL) diff --git a/client/gdaemonvfs.c b/client/gdaemonvfs.c index e4f9164a..7479bd82 100644 --- a/client/gdaemonvfs.c +++ b/client/gdaemonvfs.c @@ -983,6 +983,14 @@ g_io_module_load (GIOModule *module) if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL) return; + /* Make this module resident so that we ground the common + * library. If that is unloaded we could get into all kinds + * of strange situations. This is safe to do even if we loaded + * some other common-using module first as all modules are loaded + * before any are freed. + */ + g_type_module_use (G_TYPE_MODULE (module)); + g_daemon_vfs_register_type (G_TYPE_MODULE (module)); g_daemon_volume_monitor_register_types (G_TYPE_MODULE (module)); diff --git a/common/Makefile.am b/common/Makefile.am index 5c59496b..2fbb908b 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,6 +1,5 @@ NULL = -noinst_LTLIBRARIES = libgvfscommon-noin.la lib_LTLIBRARIES=libgvfscommon.la INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gvfs \ @@ -9,7 +8,7 @@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gvfs \ -DG_LOG_DOMAIN=\"GVFS\" -DG_DISABLE_DEPRECATED \ -DDBUS_API_SUBJECT_TO_CHANGE -libgvfscommon_noin_la_SOURCES = \ +libgvfscommon_la_SOURCES = \ gsysutils.c gsysutils.h \ gdbusutils.c gdbusutils.h \ gmountspec.c gmountspec.h \ @@ -19,9 +18,6 @@ libgvfscommon_noin_la_SOURCES = \ gvfsdaemonprotocol.c gvfsdaemonprotocol.h \ $(NULL) -libgvfscommon_noin_la_LIBADD = \ +libgvfscommon_la_LIBADD = \ $(DBUS_LIBS) \ $(GLIB_LIBS) - -libgvfscommon_la_SOURCES = -libgvfscommon_la_LIBADD = libgvfscommon-noin.la diff --git a/common/gmountsource.c b/common/gmountsource.c index bbf6d73f..e801d647 100644 --- a/common/gmountsource.c +++ b/common/gmountsource.c @@ -35,32 +35,7 @@ struct _GMountSource char *obj_path; }; -/* We use this hack to avoid problems when this code - is shared in both the daemon and the client */ -static GType _g_mount_source_get_type (void) G_GNUC_CONST; - -#define g_mount_source_get_type _g_mount_source_get_type G_DEFINE_TYPE (GMountSource, g_mount_source, G_TYPE_OBJECT) -#undef g_mount_source_get_type - -GType -g_mount_source_get_type (void) -{ - static volatile gsize type_volatile = 0; - - if (g_once_init_enter (&type_volatile)) - { - GType type; - - type = g_type_from_name ("GMountSource"); - if (type == 0) - type = _g_mount_source_get_type (); - - g_once_init_leave (&type_volatile, type); - } - - return type_volatile; -} static void g_mount_source_finalize (GObject *object) diff --git a/common/gmounttracker.c b/common/gmounttracker.c index 5d97d0c9..eba29ef5 100644 --- a/common/gmounttracker.c +++ b/common/gmounttracker.c @@ -54,33 +54,7 @@ struct _GMountTracker DBusConnection *connection; }; -/* We use this hack to avoid problems when this code - is shared in both the daemon and the client */ -static GType _g_mount_tracker_get_type (void) G_GNUC_CONST; - -#define g_mount_tracker_get_type _g_mount_tracker_get_type G_DEFINE_TYPE (GMountTracker, g_mount_tracker, G_TYPE_OBJECT) -#undef g_mount_tracker_get_type - -GType -g_mount_tracker_get_type (void) -{ - static volatile gsize type_volatile = 0; - - if (g_once_init_enter (&type_volatile)) - { - GType type; - - type = g_type_from_name ("GMountTracker"); - if (type == 0) - type = _g_mount_tracker_get_type (); - - g_once_init_leave (&type_volatile, type); - } - - return type_volatile; -} - static DBusHandlerResult g_mount_tracker_filter_func (DBusConnection *conn, DBusMessage *message, diff --git a/monitor/gphoto2/Makefile.am b/monitor/gphoto2/Makefile.am index df37aa20..5137a65e 100644 --- a/monitor/gphoto2/Makefile.am +++ b/monitor/gphoto2/Makefile.am @@ -40,7 +40,7 @@ gvfs_gphoto2_volume_monitor_LDFLAGS = \ gvfs_gphoto2_volume_monitor_LDADD = \ $(GLIB_LIBS) \ $(HAL_LIBS) \ - $(top_builddir)/common/libgvfscommon-noin.la \ + $(top_builddir)/common/libgvfscommon.la \ $(top_builddir)/monitor/proxy/libgvfsproxyvolumemonitordaemon-noin.la \ $(NULL) diff --git a/monitor/hal/Makefile.am b/monitor/hal/Makefile.am index f9d9d7e5..9c3d1777 100644 --- a/monitor/hal/Makefile.am +++ b/monitor/hal/Makefile.am @@ -42,7 +42,7 @@ gvfs_hal_volume_monitor_LDFLAGS = \ gvfs_hal_volume_monitor_LDADD = \ $(GLIB_LIBS) \ $(HAL_LIBS) \ - $(top_builddir)/common/libgvfscommon-noin.la \ + $(top_builddir)/common/libgvfscommon.la \ $(top_builddir)/monitor/proxy/libgvfsproxyvolumemonitordaemon-noin.la \ $(NULL) diff --git a/monitor/proxy/Makefile.am b/monitor/proxy/Makefile.am index 6cb7a0e3..9f1c9743 100644 --- a/monitor/proxy/Makefile.am +++ b/monitor/proxy/Makefile.am @@ -33,7 +33,7 @@ libgioremote_volume_monitor_la_LDFLAGS = \ libgioremote_volume_monitor_la_LIBADD = \ $(GLIB_LIBS) \ $(DBUS_LIBS) \ - $(top_builddir)/common/libgvfscommon-noin.la \ + $(top_builddir)/common/libgvfscommon.la \ $(NULL) ############################################################################ @@ -57,7 +57,7 @@ libgvfsproxyvolumemonitordaemon_noin_la_CFLAGS = \ libgvfsproxyvolumemonitordaemon_noin_la_LIBADD = \ $(GLIB_LIBS) \ $(DBUS_LIBS) \ - $(top_builddir)/common/libgvfscommon-noin.la \ + $(top_builddir)/common/libgvfscommon.la \ $(NULL) clean-local: diff --git a/monitor/proxy/gproxyvolumemonitor.c b/monitor/proxy/gproxyvolumemonitor.c index 06523714..e71fcde0 100644 --- a/monitor/proxy/gproxyvolumemonitor.c +++ b/monitor/proxy/gproxyvolumemonitor.c @@ -58,6 +58,7 @@ G_LOCK_DEFINE_STATIC(proxy_vm); static DBusConnection *the_session_bus = NULL; +static gboolean the_session_bus_is_integrated = FALSE; static GHashTable *the_volume_monitors = NULL; struct _GProxyVolumeMonitor { @@ -81,6 +82,30 @@ static DBusHandlerResult filter_function (DBusConnection *connection, DBusMessag static void signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object); +static gboolean is_supported (GProxyVolumeMonitorClass *klass); + +/* The is_supported API is kinda lame and doesn't pass in the class, + so we work around this with this hack */ +typedef gboolean (*is_supported_func) (void); + +static GProxyVolumeMonitorClass *is_supported_classes[10] = { NULL }; +static gboolean is_supported_0 (void) { return is_supported (is_supported_classes[0]); }; +static gboolean is_supported_1 (void) { return is_supported (is_supported_classes[1]); }; +static gboolean is_supported_2 (void) { return is_supported (is_supported_classes[2]); }; +static gboolean is_supported_3 (void) { return is_supported (is_supported_classes[3]); }; +static gboolean is_supported_4 (void) { return is_supported (is_supported_classes[4]); }; +static gboolean is_supported_5 (void) { return is_supported (is_supported_classes[5]); }; +static gboolean is_supported_6 (void) { return is_supported (is_supported_classes[6]); }; +static gboolean is_supported_7 (void) { return is_supported (is_supported_classes[7]); }; +static gboolean is_supported_8 (void) { return is_supported (is_supported_classes[8]); }; +static gboolean is_supported_9 (void) { return is_supported (is_supported_classes[9]); }; +static is_supported_func is_supported_funcs[] = { + is_supported_0, is_supported_1, is_supported_2, is_supported_3, + is_supported_4, is_supported_5, is_supported_6, is_supported_7, + is_supported_8, is_supported_9, + NULL +}; + static char * get_match_rule (GProxyVolumeMonitor *monitor) { @@ -606,6 +631,7 @@ filter_function (DBusConnection *connection, DBusMessage *message, void *user_da static void g_proxy_volume_monitor_init (GProxyVolumeMonitor *monitor) { + g_proxy_volume_monitor_setup_session_bus_connection (TRUE); } static void @@ -617,15 +643,22 @@ g_proxy_volume_monitor_class_finalize (GProxyVolumeMonitorClass *klass) typedef struct { char *dbus_name; gboolean is_native; + int is_supported_nr; } ProxyClassData; static ProxyClassData * proxy_class_data_new (const char *dbus_name, gboolean is_native) { ProxyClassData *data; + static int is_supported_nr = 0; + data = g_new0 (ProxyClassData, 1); data->dbus_name = g_strdup (dbus_name); data->is_native = is_native; + data->is_supported_nr = is_supported_nr++; + + g_assert (is_supported_funcs[data->is_supported_nr] != NULL); + return data; } @@ -635,15 +668,79 @@ g_proxy_volume_monitor_class_intern_init_pre (GProxyVolumeMonitorClass *klass, g ProxyClassData *data = (ProxyClassData *) class_data; klass->dbus_name = g_strdup (data->dbus_name); klass->is_native = data->is_native; + klass->is_supported_nr = data->is_supported_nr; g_proxy_volume_monitor_class_intern_init (klass); } static gboolean -is_supported (void) +is_remote_monitor_supported (const char *dbus_name) { - if (the_session_bus != NULL) - return TRUE; - return FALSE; + DBusMessage *message; + DBusMessage *reply; + DBusError dbus_error; + dbus_bool_t is_supported; + + message = NULL; + reply = NULL; + is_supported = FALSE; + + message = dbus_message_new_method_call (dbus_name, + "/", + "org.gtk.Private.RemoteVolumeMonitor", + "IsSupported"); + if (message == NULL) + { + g_warning ("Cannot allocate memory for DBusMessage"); + goto fail; + } + dbus_error_init (&dbus_error); + reply = dbus_connection_send_with_reply_and_block (the_session_bus, + message, + -1, + &dbus_error); + if (dbus_error_is_set (&dbus_error)) + { + g_warning ("invoking IsSupported() failed for remote volume monitor with dbus name %s: %s: %s", + dbus_name, + dbus_error.name, + dbus_error.message); + dbus_error_free (&dbus_error); + goto fail; + } + + if (!dbus_message_get_args (reply, &dbus_error, + DBUS_TYPE_BOOLEAN, &is_supported, + DBUS_TYPE_INVALID)) + { + g_warning ("Error parsing args in reply for IsSupported(): %s: %s", dbus_error.name, dbus_error.message); + dbus_error_free (&dbus_error); + goto fail; + } + + if (!is_supported) + g_warning ("remote volume monitor with dbus name %s is not supported", dbus_name); + + fail: + if (message != NULL) + dbus_message_unref (message); + if (reply != NULL) + dbus_message_unref (reply); + return is_supported; +} + +static gboolean +is_supported (GProxyVolumeMonitorClass *klass) +{ + gboolean res; + + G_LOCK (proxy_vm); + res = g_proxy_volume_monitor_setup_session_bus_connection (FALSE); + G_UNLOCK (proxy_vm); + + if (res) + res = is_remote_monitor_supported (klass->dbus_name); + + return res; } static GVolume * @@ -702,6 +799,7 @@ g_proxy_volume_monitor_class_init (GProxyVolumeMonitorClass *klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass); GNativeVolumeMonitorClass *native_class = G_NATIVE_VOLUME_MONITOR_CLASS (klass); + int i; gobject_class->constructor = g_proxy_volume_monitor_constructor; gobject_class->finalize = g_proxy_volume_monitor_finalize; @@ -712,7 +810,10 @@ g_proxy_volume_monitor_class_init (GProxyVolumeMonitorClass *klass) monitor_class->get_volume_for_uuid = get_volume_for_uuid; monitor_class->get_mount_for_uuid = get_mount_for_uuid; monitor_class->adopt_orphan_mount = adopt_orphan_mount; - monitor_class->is_supported = is_supported; + + i = klass->is_supported_nr; + is_supported_classes[i] = klass; + monitor_class->is_supported = is_supported_funcs[i]; native_class->get_mount_for_mount_path = get_mount_for_mount_path; } @@ -1041,47 +1142,47 @@ register_volume_monitor (GTypeModule *type_module, priority); } +/* Call with proxy_vm lock held */ gboolean -g_proxy_volume_monitor_setup_session_bus_connection (void) +g_proxy_volume_monitor_setup_session_bus_connection (gboolean need_integration) { gboolean ret; DBusError dbus_error; ret = FALSE; - G_LOCK (proxy_vm); if (the_session_bus != NULL) - { - g_warning ("session bus connection is already up!"); - dbus_connection_ref (the_session_bus); - goto out; - } + goto has_bus_already; /* This is so that system daemons can use gio * without spawning private dbus instances. * See bug 526454. */ if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL) - { - goto out; - } + goto out; dbus_error_init (&dbus_error); the_session_bus = dbus_bus_get_private (DBUS_BUS_SESSION, &dbus_error); - if (dbus_error_is_set (&dbus_error)) { - g_warning ("cannot connect to the session bus: %s: %s", dbus_error.name, dbus_error.message); - dbus_error_free (&dbus_error); - goto out; - } - - _g_dbus_connection_integrate_with_main (the_session_bus); + if (dbus_error_is_set (&dbus_error)) + { + g_warning ("cannot connect to the session bus: %s: %s", dbus_error.name, dbus_error.message); + dbus_error_free (&dbus_error); + goto out; + } the_volume_monitors = g_hash_table_new (g_direct_hash, g_direct_equal); + has_bus_already: + + if (need_integration && !the_session_bus_is_integrated) + { + _g_dbus_connection_integrate_with_main (the_session_bus); + the_session_bus_is_integrated = TRUE; + } + ret = TRUE; out: - G_UNLOCK (proxy_vm); return ret; } @@ -1091,8 +1192,9 @@ g_proxy_volume_monitor_teardown_session_bus_connection (void) G_LOCK (proxy_vm); if (the_session_bus != NULL) { - /* it would be nice to check that refcount==1 here */ - _g_dbus_connection_remove_from_main (the_session_bus); + if (the_session_bus_is_integrated) + _g_dbus_connection_remove_from_main (the_session_bus); + the_session_bus_is_integrated = FALSE; dbus_connection_close (the_session_bus); the_session_bus = NULL; @@ -1102,62 +1204,6 @@ g_proxy_volume_monitor_teardown_session_bus_connection (void) G_UNLOCK (proxy_vm); } -static gboolean -is_remote_monitor_supported (const char *dbus_name) -{ - DBusMessage *message; - DBusMessage *reply; - DBusError dbus_error; - dbus_bool_t is_supported; - - message = NULL; - reply = NULL; - is_supported = FALSE; - - message = dbus_message_new_method_call (dbus_name, - "/", - "org.gtk.Private.RemoteVolumeMonitor", - "IsSupported"); - if (message == NULL) - { - g_warning ("Cannot allocate memory for DBusMessage"); - goto fail; - } - dbus_error_init (&dbus_error); - reply = dbus_connection_send_with_reply_and_block (the_session_bus, - message, - -1, - &dbus_error); - if (dbus_error_is_set (&dbus_error)) - { - g_warning ("invoking IsSupported() failed for remote volume monitor with dbus name %s: %s: %s", - dbus_name, - dbus_error.name, - dbus_error.message); - dbus_error_free (&dbus_error); - goto fail; - } - - if (!dbus_message_get_args (reply, &dbus_error, - DBUS_TYPE_BOOLEAN, &is_supported, - DBUS_TYPE_INVALID)) - { - g_warning ("Error parsing args in reply for IsSupported(): %s: %s", dbus_error.name, dbus_error.message); - dbus_error_free (&dbus_error); - goto fail; - } - - if (!is_supported) - g_warning ("remote volume monitor with dbus name %s is not supported", dbus_name); - - fail: - if (message != NULL) - dbus_message_unref (message); - if (reply != NULL) - dbus_message_unref (reply); - return is_supported; -} - void g_proxy_volume_monitor_register (GIOModule *module) { @@ -1256,14 +1302,11 @@ g_proxy_volume_monitor_register (GIOModule *module) native_priority = 0; } - if (is_remote_monitor_supported (dbus_name)) - { - register_volume_monitor (G_TYPE_MODULE (module), - type_name, - dbus_name, - is_native, - native_priority); - } + register_volume_monitor (G_TYPE_MODULE (module), + type_name, + dbus_name, + is_native, + native_priority); cont: diff --git a/monitor/proxy/gproxyvolumemonitor.h b/monitor/proxy/gproxyvolumemonitor.h index eb2f9316..4768ba8f 100644 --- a/monitor/proxy/gproxyvolumemonitor.h +++ b/monitor/proxy/gproxyvolumemonitor.h @@ -49,6 +49,7 @@ struct _GProxyVolumeMonitorClass { GNativeVolumeMonitorClass parent_class; char *dbus_name; gboolean is_native; + int is_supported_nr; }; GType g_proxy_volume_monitor_get_type (void) G_GNUC_CONST; @@ -63,7 +64,7 @@ GProxyMount *g_proxy_volume_monitor_get_mount_for_id (GProxyVolumeMonitor *v DBusConnection *g_proxy_volume_monitor_get_dbus_connection (GProxyVolumeMonitor *volume_monitor); const char *g_proxy_volume_monitor_get_dbus_name (GProxyVolumeMonitor *volume_monitor); -gboolean g_proxy_volume_monitor_setup_session_bus_connection (void); +gboolean g_proxy_volume_monitor_setup_session_bus_connection (gboolean need_integration); void g_proxy_volume_monitor_teardown_session_bus_connection (void); diff --git a/monitor/proxy/remote-volume-monitor-module.c b/monitor/proxy/remote-volume-monitor-module.c index f675bc41..90945141 100644 --- a/monitor/proxy/remote-volume-monitor-module.c +++ b/monitor/proxy/remote-volume-monitor-module.c @@ -43,9 +43,6 @@ g_io_module_load (GIOModule *module) bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - if (!g_proxy_volume_monitor_setup_session_bus_connection ()) - goto out; - g_proxy_drive_register (module); g_proxy_mount_register (module); g_proxy_volume_register (module); |