diff options
author | Jiří Klimeš <jklimes@redhat.com> | 2014-03-17 13:38:45 +0100 |
---|---|---|
committer | Jiří Klimeš <jklimes@redhat.com> | 2014-03-17 13:38:45 +0100 |
commit | 9e8b0ff01633b31f7ee9eb1590fb24ce674dc358 (patch) | |
tree | 54584b884a6ee9dd5bb0555826aa3c03704a72bf | |
parent | a1e89b4d29b97695f21e0070888f7910f7fe7a87 (diff) | |
download | NetworkManager-jk/rh1050934-vpn-plugin-init.tar.gz |
libnm-glib: fix crash when NMVPNPlugin unrefs self in constructor (rh #1050934)jk/rh1050934-vpn-plugin-init
When NMVPNPlugin encountered an error at construct time, it would unref itself
and return NULL. glib 2.39 will g_error() out in this case, because you're not
supposed to do that, and because it used to cause mysterious crashes later on
if you did.
Fix this by using GInitable to initialize NMVPNPlugin rather than trying to do
it from constructor().
See also
https://mail.gnome.org/archives/commits-list/2013-October/msg07491.html
https://bugzilla.redhat.com/show_bug.cgi?id=1050934
-rw-r--r-- | libnm-glib/nm-vpn-plugin.c | 78 |
1 files changed, 36 insertions, 42 deletions
diff --git a/libnm-glib/nm-vpn-plugin.c b/libnm-glib/nm-vpn-plugin.c index d5a2b69c76..56cef94fe1 100644 --- a/libnm-glib/nm-vpn-plugin.c +++ b/libnm-glib/nm-vpn-plugin.c @@ -18,10 +18,11 @@ * Boston, MA 02110-1301 USA. * * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2008 Red Hat, Inc. + * Copyright (C) 2007 - 2014 Red Hat, Inc. */ #include <signal.h> +#include <gio/gio.h> #include "nm-glib-compat.h" #include "nm-vpn-plugin.h" #include "nm-vpn-enum-types.h" @@ -70,7 +71,12 @@ static gboolean impl_vpn_plugin_set_failure (NMVPNPlugin *plugin, #define NM_VPN_PLUGIN_QUIT_TIMER 20 -G_DEFINE_ABSTRACT_TYPE (NMVPNPlugin, nm_vpn_plugin, G_TYPE_OBJECT) +static void nm_vpn_plugin_initable_interface_init (GInitableIface *iface, gpointer iface_data); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMVPNPlugin, nm_vpn_plugin, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + nm_vpn_plugin_initable_interface_init) + ) typedef struct { NMVPNServiceState state; @@ -731,75 +737,57 @@ nm_vpn_plugin_init (NMVPNPlugin *plugin) { active_plugins = g_slist_append (active_plugins, plugin); g_object_weak_ref (G_OBJECT (plugin), - one_plugin_destroyed, - NULL); + one_plugin_destroyed, + NULL); } -static GObject * -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static gboolean +initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { - GObject *object; - NMVPNPlugin *plugin; + NMVPNPlugin *plugin = NM_VPN_PLUGIN (initable); NMVPNPluginPrivate *priv; DBusGConnection *connection; DBusGProxy *proxy; guint request_name_result; - GError *err = NULL; - - object = G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - priv = NM_VPN_PLUGIN_GET_PRIVATE (object); - if (!priv->dbus_service_name) - goto err; + priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); + if (!priv->dbus_service_name) { + g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL, + "Failed to initialize VPN plugin: D-Bus service name is missing"); + return FALSE; + } - connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); - if (!connection) - goto err; + connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, error); + if (!connection) { + g_prefix_error (error, "Failed to initialize VPN plugin (D-Bus): "); + return FALSE; + } proxy = dbus_g_proxy_new_for_name (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); - if (!dbus_g_proxy_call (proxy, "RequestName", &err, + if (!dbus_g_proxy_call (proxy, "RequestName", error, G_TYPE_STRING, priv->dbus_service_name, G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &request_name_result, G_TYPE_INVALID)) { g_object_unref (proxy); - goto err; + g_prefix_error (error, "Failed to initialize VPN plugin; 'RequestName' call failure: "); + return FALSE; } - g_object_unref (proxy); dbus_g_connection_register_g_object (connection, NM_VPN_DBUS_PLUGIN_PATH, - object); - - plugin = NM_VPN_PLUGIN (object); + G_OBJECT (plugin)); nm_vpn_plugin_set_connection (plugin, connection); nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_INIT); - return object; - - err: - if (err) { - g_warning ("Failed to initialize VPN plugin: %s", err->message); - g_error_free (err); - } - - if (object) - g_object_unref (object); - - return NULL; + return TRUE; } static void @@ -946,7 +934,6 @@ nm_vpn_plugin_class_init (NMVPNPluginClass *plugin_class) &dbus_glib_nm_vpn_plugin_object_info); /* virtual methods */ - object_class->constructor = constructor; object_class->set_property = set_property; object_class->get_property = get_property; object_class->dispose = dispose; @@ -1058,3 +1045,10 @@ nm_vpn_plugin_class_init (NMVPNPluginClass *plugin_class) setup_unix_signal_handler (); } + +static void +nm_vpn_plugin_initable_interface_init (GInitableIface *iface, gpointer iface_data) +{ + iface->init = initable_init; +} + |