Bug#696669: unblock: network-manager/0.9.4.0-7
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
Please unblock package network-manager
It fixes two RC bugs.
The patches for the libnm-glib are somewhat largeish, but they are taken
from upstream and have been part of network-manager 0.9.6, which has
been released for quite some time and is also available from
experimental for over 2 months without any related bug report.
The full changelog is
network-manager (0.9.4.0-7) unstable; urgency=low
* Install a PolicyKit pkla file which allows members of group netdev or sudo
to create system-wide network connections without being prompted for the
admin password. (Closes: #642136)
* Cherry-pick patches for libnm-glib which fix various segfaults e.g. in
gnome-control-center when switching between overview and network settings
panel or in gnome-shell and nm-applet when restarting NetworkManager.
(Closes: #696143) (bgo: #674473)
-- Michael Biebl <biebl@debian.org> Fri, 21 Dec 2012 03:48:18 +0100
Complete debdiff is attached.
Cheers,
Michael
unblock network-manager/0.9.4.0-7
-- System Information:
Debian Release: 7.0
APT prefers unstable
APT policy: (500, 'unstable'), (200, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 3.6-trunk-amd64 (SMP w/4 CPU cores)
Locale: LANG=de_DE.utf8, LC_CTYPE=de_DE.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff --git a/debian/changelog b/debian/changelog
index 8b905b9..1d27379 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+network-manager (0.9.4.0-7) unstable; urgency=low
+
+ * Install a PolicyKit pkla file which allows members of group netdev or sudo
+ to create system-wide network connections without being prompted for the
+ admin password. (Closes: #642136)
+ * Cherry-pick patches for libnm-glib which fix various segfaults e.g. in
+ gnome-control-center when switching between overview and network settings
+ panel or in gnome-shell and nm-applet when restarting NetworkManager.
+ (Closes: #696143) (bgo: #674473)
+
+ -- Michael Biebl <biebl@debian.org> Fri, 21 Dec 2012 03:48:18 +0100
+
network-manager (0.9.4.0-6) unstable; urgency=low
* debian/rules: Use xz compression for binary packages.
diff --git a/debian/network-manager.install b/debian/network-manager.install
index 35b81be..6bd49d2 100644
--- a/debian/network-manager.install
+++ b/debian/network-manager.install
@@ -21,3 +21,4 @@ lib/udev/rules.d/*.rules
lib/systemd/system/NetworkManager.service
lib/systemd/system/NetworkManager-wait-online.service
debian/NetworkManager.conf etc/NetworkManager/
+debian/org.freedesktop.NetworkManager.pkla var/lib/polkit-1/localauthority/10-vendor.d/
diff --git a/debian/org.freedesktop.NetworkManager.pkla b/debian/org.freedesktop.NetworkManager.pkla
new file mode 100644
index 0000000..7acba4e
--- /dev/null
+++ b/debian/org.freedesktop.NetworkManager.pkla
@@ -0,0 +1,6 @@
+[Adding or changing system-wide NetworkManager connections]
+Identity=unix-group:netdev;unix-group:sudo
+Action=org.freedesktop.NetworkManager.settings.modify.system
+ResultAny=no
+ResultInactive=no
+ResultActive=yes
diff --git a/debian/patches/18-libnm-glib-NULL-out-priv-fields-on-dispose.patch b/debian/patches/18-libnm-glib-NULL-out-priv-fields-on-dispose.patch
new file mode 100644
index 0000000..74a86a4
--- /dev/null
+++ b/debian/patches/18-libnm-glib-NULL-out-priv-fields-on-dispose.patch
@@ -0,0 +1,670 @@
+From be18dd06cd138be232ff68ec7af19cfcf2f969ed Mon Sep 17 00:00:00 2001
+From: Dan Winship <danw@gnome.org>
+Date: Mon, 23 Apr 2012 15:02:48 +0000
+Subject: libnm-glib: NULL out priv fields on dispose()
+
+In some situations, objects might get used after being disposed, so
+clear out their various priv fields so we don't try to access unreffed
+objects, freed strings, etc.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=674473
+---
+Index: network-manager/include/nm-glib-compat.h
+===================================================================
+--- network-manager.orig/include/nm-glib-compat.h 2012-10-30 21:02:36.779282426 +0100
++++ network-manager/include/nm-glib-compat.h 2012-12-21 01:13:58.030742565 +0100
+@@ -42,6 +42,16 @@
+ g_simple_async_result_set_from_error (result, __error); \
+ g_error_free (__error); \
+ } G_STMT_END
++
++#define g_clear_object(object_ptr) \
++ G_STMT_START { \
++ GObject **__obj_p = object_ptr; \
++ if (*__obj_p) { \
++ g_object_unref (*__obj_p); \
++ *__obj_p = NULL; \
++ } \
++ } G_STMT_END
++
+ #endif
+
+ #endif /* NM_GLIB_COMPAT_H */
+Index: network-manager/libnm-glib/nm-access-point.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-access-point.c 2012-10-30 21:02:36.783282401 +0100
++++ network-manager/libnm-glib/nm-access-point.c 2012-12-21 01:13:58.030742565 +0100
+@@ -41,7 +41,6 @@
+ #define NM_ACCESS_POINT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACCESS_POINT, NMAccessPointPrivate))
+
+ typedef struct {
+- gboolean disposed;
+ DBusGProxy *proxy;
+
+ NM80211ApFlags flags;
+@@ -431,14 +430,7 @@
+ {
+ NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_access_point_parent_class)->dispose (object);
+- return;
+- }
+-
+- priv->disposed = TRUE;
+-
+- g_object_unref (priv->proxy);
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_access_point_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-active-connection.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-active-connection.c 2012-10-30 21:02:36.783282401 +0100
++++ network-manager/libnm-glib/nm-active-connection.c 2012-12-21 01:13:58.034742595 +0100
+@@ -49,7 +49,6 @@
+ #define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate))
+
+ typedef struct {
+- gboolean disposed;
+ DBusGProxy *proxy;
+
+ char *connection;
+@@ -357,18 +356,13 @@
+ {
+ NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
+- return;
+- }
+-
+- priv->disposed = TRUE;
+-
+ if (priv->devices) {
+ g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
+ g_ptr_array_free (priv->devices, TRUE);
++ priv->devices = NULL;
+ }
+- g_object_unref (priv->proxy);
++
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-client.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-client.c 2012-10-30 21:02:36.783282401 +0100
++++ network-manager/libnm-glib/nm-client.c 2012-12-21 01:13:58.034742595 +0100
+@@ -53,8 +53,6 @@
+ #define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate))
+
+ typedef struct {
+- gboolean disposed;
+-
+ DBusGProxy *client_proxy;
+ DBusGProxy *bus_proxy;
+ gboolean manager_running;
+@@ -1419,24 +1417,23 @@
+ {
+ NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
+- return;
+- }
+-
+- if (priv->perm_call)
++ if (priv->perm_call) {
+ dbus_g_proxy_cancel_call (priv->client_proxy, priv->perm_call);
++ priv->perm_call = NULL;
++ }
+
+- g_object_unref (priv->client_proxy);
+- g_object_unref (priv->bus_proxy);
++ g_clear_object (&priv->client_proxy);
++ g_clear_object (&priv->bus_proxy);
+
+ free_object_array (&priv->devices);
+ dispose_and_free_object_array (&priv->active_connections);
+
+ g_slist_foreach (priv->pending_activations, (GFunc) activate_info_free, NULL);
+ g_slist_free (priv->pending_activations);
++ priv->pending_activations = NULL;
+
+ g_hash_table_destroy (priv->permissions);
++ priv->permissions = NULL;
+
+ G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device-bond.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device-bond.c 2012-10-30 21:02:36.783282401 +0100
++++ network-manager/libnm-glib/nm-device-bond.c 2012-12-21 01:13:58.034742595 +0100
+@@ -215,10 +215,7 @@
+ {
+ NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object);
+
+- if (priv->proxy) {
+- g_object_unref (priv->proxy);
+- priv->proxy = NULL;
+- }
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_device_bond_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device-bt.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device-bt.c 2012-10-30 21:02:36.783282401 +0100
++++ network-manager/libnm-glib/nm-device-bt.c 2012-12-21 01:13:58.034742595 +0100
+@@ -42,8 +42,6 @@
+ char *hw_address;
+ char *name;
+ guint32 bt_capabilities;
+-
+- gboolean disposed;
+ } NMDeviceBtPrivate;
+
+ enum {
+@@ -273,13 +271,7 @@
+ {
+ NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object);
+- return;
+- }
+- priv->disposed = TRUE;
+-
+- g_object_unref (priv->proxy);
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device-ethernet.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device-ethernet.c 2012-10-30 21:02:36.783282401 +0100
++++ network-manager/libnm-glib/nm-device-ethernet.c 2012-12-21 01:13:58.034742595 +0100
+@@ -44,8 +44,6 @@
+ char *perm_hw_address;
+ guint32 speed;
+ gboolean carrier;
+-
+- gboolean disposed;
+ } NMDeviceEthernetPrivate;
+
+ enum {
+@@ -280,14 +278,7 @@
+ {
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
+- return;
+- }
+-
+- priv->disposed = TRUE;
+-
+- g_object_unref (priv->proxy);
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device-infiniband.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device-infiniband.c 2012-10-30 21:02:36.783282401 +0100
++++ network-manager/libnm-glib/nm-device-infiniband.c 2012-12-21 01:13:58.034742595 +0100
+@@ -224,10 +224,7 @@
+ {
+ NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object);
+
+- if (priv->proxy) {
+- g_object_unref (priv->proxy);
+- priv->proxy = NULL;
+- }
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_device_infiniband_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device-modem.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device-modem.c 2012-10-30 21:02:36.783282401 +0100
++++ network-manager/libnm-glib/nm-device-modem.c 2012-12-21 01:13:58.034742595 +0100
+@@ -44,8 +44,6 @@
+
+ NMDeviceModemCapabilities caps;
+ NMDeviceModemCapabilities current_caps;
+-
+- gboolean disposed;
+ } NMDeviceModemPrivate;
+
+ enum {
+@@ -223,14 +221,7 @@
+ {
+ NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_device_modem_parent_class)->dispose (object);
+- return;
+- }
+-
+- priv->disposed = TRUE;
+-
+- g_object_unref (priv->proxy);
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_device_modem_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device-olpc-mesh.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device-olpc-mesh.c 2012-10-30 21:02:36.783282401 +0100
++++ network-manager/libnm-glib/nm-device-olpc-mesh.c 2012-12-21 01:13:58.034742595 +0100
+@@ -227,14 +227,8 @@
+ {
+ NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object);
+
+- if (priv->companion) {
+- g_object_unref (priv->companion);
+- priv->companion = NULL;
+- }
+- if (priv->proxy) {
+- g_object_unref (priv->proxy);
+- priv->proxy = NULL;
+- }
++ g_clear_object (&priv->companion);
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device-vlan.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device-vlan.c 2012-10-30 21:02:36.787282377 +0100
++++ network-manager/libnm-glib/nm-device-vlan.c 2012-12-21 01:13:58.034742595 +0100
+@@ -238,10 +238,7 @@
+ {
+ NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object);
+
+- if (priv->proxy) {
+- g_object_unref (priv->proxy);
+- priv->proxy = NULL;
+- }
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device-wifi.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device-wifi.c 2012-10-30 21:02:36.787282377 +0100
++++ network-manager/libnm-glib/nm-device-wifi.c 2012-12-21 01:13:58.034742595 +0100
+@@ -43,7 +43,6 @@
+ void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
+
+ typedef struct {
+- gboolean disposed;
+ DBusGProxy *proxy;
+
+ char *hw_address;
+@@ -606,15 +605,8 @@
+ {
+ NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
+- return;
+- }
+-
+- priv->disposed = TRUE;
+-
+ clean_up_aps (NM_DEVICE_WIFI (object), FALSE);
+- g_object_unref (priv->proxy);
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device-wimax.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device-wimax.c 2012-10-30 21:02:36.787282377 +0100
++++ network-manager/libnm-glib/nm-device-wimax.c 2012-12-21 01:13:58.034742595 +0100
+@@ -42,7 +42,6 @@
+ void _nm_device_wimax_set_wireless_enabled (NMDeviceWimax *wimax, gboolean enabled);
+
+ typedef struct {
+- gboolean disposed;
+ DBusGProxy *proxy;
+
+ char *hw_address;
+@@ -591,18 +590,18 @@
+ {
+ NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object);
+- return;
++ if (priv->hw_address) {
++ g_free (priv->hw_address);
++ priv->hw_address = NULL;
+ }
+
+- priv->disposed = TRUE;
+-
+- g_free (priv->hw_address);
+- g_free (priv->bsid);
++ if (priv->bsid) {
++ g_free (priv->bsid);
++ priv->bsid = NULL;
++ }
+
+ clean_up_nsps (NM_DEVICE_WIMAX (object), FALSE);
+- g_object_unref (priv->proxy);
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-device.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-device.c 2012-10-30 21:02:36.787282377 +0100
++++ network-manager/libnm-glib/nm-device.c 2012-12-21 01:13:58.038742626 +0100
+@@ -60,7 +60,6 @@
+ #define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
+
+ typedef struct {
+- gboolean disposed;
+ DBusGProxy *proxy;
+
+ char *iface;
+@@ -265,26 +264,13 @@
+ {
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
+- return;
+- }
+-
+- priv->disposed = TRUE;
+-
+- g_object_unref (priv->proxy);
+- if (priv->ip4_config)
+- g_object_unref (priv->ip4_config);
+- if (priv->dhcp4_config)
+- g_object_unref (priv->dhcp4_config);
+- if (priv->ip6_config)
+- g_object_unref (priv->ip6_config);
+- if (priv->dhcp6_config)
+- g_object_unref (priv->dhcp6_config);
+- if (priv->client)
+- g_object_unref (priv->client);
+- if (priv->active_connection)
+- g_object_unref (priv->active_connection);
++ g_clear_object (&priv->proxy);
++ g_clear_object (&priv->ip4_config);
++ g_clear_object (&priv->dhcp4_config);
++ g_clear_object (&priv->ip6_config);
++ g_clear_object (&priv->dhcp6_config);
++ g_clear_object (&priv->client);
++ g_clear_object (&priv->active_connection);
+
+ G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-object.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-object.c 2012-10-30 21:02:36.787282377 +0100
++++ network-manager/libnm-glib/nm-object.c 2012-12-21 01:13:58.038742626 +0100
+@@ -78,7 +78,7 @@
+
+ GSList *notify_props;
+ guint32 notify_id;
+- gboolean inited, disposed;
++ gboolean inited;
+
+ GSList *reload_results;
+ guint reload_remaining;
+@@ -194,13 +194,6 @@
+ {
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_object_parent_class)->dispose (object);
+- return;
+- }
+-
+- priv->disposed = TRUE;
+-
+ if (priv->notify_id) {
+ g_source_remove (priv->notify_id);
+ priv->notify_id = 0;
+@@ -208,12 +201,18 @@
+
+ g_slist_foreach (priv->notify_props, (GFunc) g_free, NULL);
+ g_slist_free (priv->notify_props);
++ priv->notify_props = NULL;
+
+ g_slist_foreach (priv->property_interfaces, (GFunc) g_free, NULL);
+ g_slist_free (priv->property_interfaces);
++ priv->property_interfaces = NULL;
+
+- g_object_unref (priv->properties_proxy);
+- dbus_g_connection_unref (priv->connection);
++ g_clear_object (&priv->properties_proxy);
++
++ if (priv->connection) {
++ dbus_g_connection_unref (priv->connection);
++ priv->connection = NULL;
++ }
+
+ G_OBJECT_CLASS (nm_object_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-remote-connection.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-remote-connection.c 2012-10-30 21:02:36.787282377 +0100
++++ network-manager/libnm-glib/nm-remote-connection.c 2012-12-21 01:13:58.038742626 +0100
+@@ -72,7 +72,6 @@
+ GSList *calls;
+
+ gboolean visible;
+- gboolean disposed;
+ } NMRemoteConnectionPrivate;
+
+ #define NM_REMOTE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionPrivate))
+@@ -477,14 +476,14 @@
+ NMRemoteConnection *self = NM_REMOTE_CONNECTION (object);
+ NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object);
+
+- if (!priv->disposed) {
+- priv->disposed = TRUE;
++ while (g_slist_length (priv->calls))
++ remote_call_complete (self, priv->calls->data);
+
+- while (g_slist_length (priv->calls))
+- remote_call_complete (self, priv->calls->data);
++ g_clear_object (&priv->proxy);
+
+- g_object_unref (priv->proxy);
++ if (priv->bus) {
+ dbus_g_connection_unref (priv->bus);
++ priv->bus = NULL;
+ }
+
+ G_OBJECT_CLASS (nm_remote_connection_parent_class)->dispose (object);
+Index: network-manager/libnm-glib/nm-remote-settings.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-remote-settings.c 2012-12-21 01:13:57.994742293 +0100
++++ network-manager/libnm-glib/nm-remote-settings.c 2012-12-21 01:13:58.038742626 +0100
+@@ -61,8 +61,6 @@
+ DBusGProxy *dbus_proxy;
+
+ guint fetch_id;
+-
+- gboolean disposed;
+ } NMRemoteSettingsPrivate;
+
+ enum {
+@@ -1012,29 +1010,35 @@
+ NMRemoteSettings *self = NM_REMOTE_SETTINGS (object);
+ NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+
+- if (priv->disposed)
+- return;
+-
+- priv->disposed = TRUE;
+-
+- if (priv->fetch_id)
++ if (priv->fetch_id) {
+ g_source_remove (priv->fetch_id);
++ priv->fetch_id = 0;
++ }
+
+ while (g_slist_length (priv->add_list))
+ add_connection_info_dispose (self, (AddConnectionInfo *) priv->add_list->data);
+
+- if (priv->connections)
++ if (priv->connections) {
+ g_hash_table_destroy (priv->connections);
++ priv->connections = NULL;
++ }
+
+- if (priv->pending)
++ if (priv->pending) {
+ g_hash_table_destroy (priv->pending);
++ priv->pending = NULL;
++ }
+
+ g_free (priv->hostname);
++ priv->hostname = NULL;
+
+- g_object_unref (priv->dbus_proxy);
+- g_object_unref (priv->proxy);
+- g_object_unref (priv->props_proxy);
+- dbus_g_connection_unref (priv->bus);
++ g_clear_object (&priv->dbus_proxy);
++ g_clear_object (&priv->proxy);
++ g_clear_object (&priv->props_proxy);
++
++ if (priv->bus) {
++ dbus_g_connection_unref (priv->bus);
++ priv->bus = NULL;
++ }
+
+ G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object);
+ }
+Index: network-manager/libnm-glib/nm-secret-agent.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-secret-agent.c 2012-10-30 21:02:36.787282377 +0100
++++ network-manager/libnm-glib/nm-secret-agent.c 2012-12-21 01:13:58.038742626 +0100
+@@ -79,8 +79,6 @@
+ gboolean auto_register;
+ gboolean suppress_auto;
+ gboolean auto_register_id;
+-
+- gboolean disposed;
+ } NMSecretAgentPrivate;
+
+ enum {
+@@ -878,29 +876,28 @@
+ NMSecretAgent *self = NM_SECRET_AGENT (object);
+ NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
+
+- if (!priv->disposed) {
+- priv->disposed = TRUE;
+-
+- if (priv->registered)
+- nm_secret_agent_unregister (self);
+-
+- if (priv->auto_register_id)
+- g_source_remove (priv->auto_register_id);
++ if (priv->registered)
++ nm_secret_agent_unregister (self);
+
+- g_free (priv->identifier);
+- g_free (priv->nm_owner);
++ if (priv->auto_register_id) {
++ g_source_remove (priv->auto_register_id);
++ priv->auto_register_id = 0;
++ }
+
+- while (priv->pending_gets)
+- get_secrets_info_finalize (self, priv->pending_gets->data);
++ g_free (priv->identifier);
++ priv->identifier = NULL;
++ g_free (priv->nm_owner);
++ priv->nm_owner = NULL;
+
+- if (priv->dbus_proxy)
+- g_object_unref (priv->dbus_proxy);
++ while (priv->pending_gets)
++ get_secrets_info_finalize (self, priv->pending_gets->data);
+
+- if (priv->manager_proxy)
+- g_object_unref (priv->manager_proxy);
++ g_clear_object (&priv->dbus_proxy);
++ g_clear_object (&priv->manager_proxy);
+
+- if (priv->bus)
+- dbus_g_connection_unref (priv->bus);
++ if (priv->bus) {
++ dbus_g_connection_unref (priv->bus);
++ priv->bus = NULL;
+ }
+
+ G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object);
+Index: network-manager/libnm-glib/nm-vpn-plugin.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-vpn-plugin.c 2012-10-30 21:02:36.791282354 +0100
++++ network-manager/libnm-glib/nm-vpn-plugin.c 2012-12-21 01:13:58.038742626 +0100
+@@ -63,9 +63,6 @@
+ DBusGConnection *connection;
+ char *dbus_service_name;
+
+- /* GObject-y stuff */
+- gboolean disposed;
+-
+ /* Temporary stuff */
+ guint connect_timer;
+ guint quit_timer;
+@@ -590,15 +587,10 @@
+ NMVPNServiceState state;
+ GError *err = NULL;
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->dispose (object);
+- return;
+- }
+-
+- priv->disposed = TRUE;
+-
+- if (priv->fail_stop_id)
++ if (priv->fail_stop_id) {
+ g_source_remove (priv->fail_stop_id);
++ priv->fail_stop_id = 0;
++ }
+
+ state = nm_vpn_plugin_get_state (plugin);
+
+Index: network-manager/libnm-glib/nm-wimax-nsp.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-wimax-nsp.c 2012-10-30 21:02:36.791282354 +0100
++++ network-manager/libnm-glib/nm-wimax-nsp.c 2012-12-21 01:13:58.038742626 +0100
+@@ -37,7 +37,6 @@
+ #define NM_WIMAX_NSP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_NSP, NMWimaxNspPrivate))
+
+ typedef struct {
+- gboolean disposed;
+ DBusGProxy *proxy;
+
+ char *name;
+@@ -217,14 +216,7 @@
+ {
+ NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object);
+
+- if (priv->disposed) {
+- G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->dispose (object);
+- return;
+- }
+-
+- priv->disposed = TRUE;
+-
+- g_object_unref (priv->proxy);
++ g_clear_object (&priv->proxy);
+
+ G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->dispose (object);
+ }
diff --git a/debian/patches/19-libnm-glib-discard-devices-and-active-connections-on-stop.patch b/debian/patches/19-libnm-glib-discard-devices-and-active-connections-on-stop.patch
new file mode 100644
index 0000000..96a7cc7
--- /dev/null
+++ b/debian/patches/19-libnm-glib-discard-devices-and-active-connections-on-stop.patch
@@ -0,0 +1,112 @@
+commit 17d5973ef64b9f0c35bd13581eb244cf137f5794
+Author: Dan Winship <danw@gnome.org>
+Date: Mon Apr 23 12:20:14 2012 -0400
+
+ libnm-glib: discard devices and active connections when NM goes down
+
+ When NMClient changes state to "not running", don't just unref all the
+ devices and connections: emit notify::active-connections and
+ device-removed signals too, so the app will drop its copies of them.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=674473
+
+Index: network-manager/libnm-glib/nm-client.c
+===================================================================
+--- network-manager.orig/libnm-glib/nm-client.c 2012-12-21 02:12:37.001171147 +0100
++++ network-manager/libnm-glib/nm-client.c 2012-12-21 02:12:40.441204970 +0100
+@@ -1016,30 +1016,50 @@
+ /****************************************************************/
+
+ static void
+-free_object_array (GPtrArray **array)
++free_devices (NMClient *client, gboolean emit_signals)
+ {
+- g_return_if_fail (array != NULL);
++ NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
++ GPtrArray *devices;
++ NMDevice *device;
++ int i;
++
++ if (!priv->devices)
++ return;
+
+- if (*array) {
+- g_ptr_array_foreach (*array, (GFunc) g_object_unref, NULL);
+- g_ptr_array_free (*array, TRUE);
+- *array = NULL;
++ devices = priv->devices;
++ priv->devices = NULL;
++ for (i = 0; i < devices->len; i++) {
++ device = devices->pdata[i];
++ if (emit_signals)
++ g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
++ g_object_unref (device);
+ }
++ g_ptr_array_free (devices, TRUE);
+ }
+
+ static void
+-dispose_and_free_object_array (GPtrArray **array)
++free_active_connections (NMClient *client, gboolean emit_signals)
+ {
+- g_return_if_fail (array != NULL);
++ NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
++ GPtrArray *active_connections;
++ NMActiveConnection *active_connection;
++ int i;
+
+- if (*array) {
+- /* The objects in the array may have circular refs with other
+- * objects, which the caller will need to know to break by
+- * calling this function rather than free_object_array().
+- */
+- g_ptr_array_foreach (*array, (GFunc) g_object_run_dispose, NULL);
+- free_object_array (array);
++ if (!priv->active_connections)
++ return;
++
++ active_connections = priv->active_connections;
++ priv->active_connections = NULL;
++ for (i = 0; i < active_connections->len; i++) {
++ active_connection = active_connections->pdata[i];
++ /* Break circular refs */
++ g_object_run_dispose (G_OBJECT (active_connection));
++ g_object_unref (active_connection);
+ }
++ g_ptr_array_free (active_connections, TRUE);
++
++ if (emit_signals)
++ g_object_notify (G_OBJECT (client), NM_CLIENT_ACTIVE_CONNECTIONS);
+ }
+
+ static void
+@@ -1086,8 +1106,8 @@
+ _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
+ _nm_object_suppress_property_updates (NM_OBJECT (client), TRUE);
+ poke_wireless_devices_with_rf_status (client);
+- free_object_array (&priv->devices);
+- dispose_and_free_object_array (&priv->active_connections);
++ free_devices (client, TRUE);
++ free_active_connections (client, TRUE);
+ priv->wireless_enabled = FALSE;
+ priv->wireless_hw_enabled = FALSE;
+ priv->wwan_enabled = FALSE;
+@@ -1415,6 +1435,7 @@
+ static void
+ dispose (GObject *object)
+ {
++ NMClient *client = NM_CLIENT (object);
+ NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
+
+ if (priv->perm_call) {
+@@ -1425,8 +1446,8 @@
+ g_clear_object (&priv->client_proxy);
+ g_clear_object (&priv->bus_proxy);
+
+- free_object_array (&priv->devices);
+- dispose_and_free_object_array (&priv->active_connections);
++ free_devices (client, FALSE);
++ free_active_connections (client, FALSE);
+
+ g_slist_foreach (priv->pending_activations, (GFunc) activate_info_free, NULL);
+ g_slist_free (priv->pending_activations);
diff --git a/debian/patches/20-libnm-glib-clear-object-cache-on-stop.patch b/debian/patches/20-libnm-glib-clear-object-cache-on-stop.patch
new file mode 100644
index 0000000..67f2406
--- /dev/null
+++ b/debian/patches/20-libnm-glib-clear-object-cache-on-stop.patch
@@ -0,0 +1,72 @@
+commit 48981a6166208152890b6c57af19cc3c5db5837f
+Author: Dan Williams <dcbw@redhat.com>
+Date: Mon Apr 23 17:07:18 2012 -0500
+
+ libnm-glib: ensure object cache is cleared when NM stops (bgo #674473)
+
+ Otherwise if a client holds references to the objects (or in the
+ JavaScript case, uses deferred garbage collection) they'll still
+ be in the cache when NM restarts, and the old object may have the
+ same path as some new object, which isn't good.
+
+diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c
+index bed1b4e..311b1d2 100644
+--- a/libnm-glib/nm-client.c
++++ b/libnm-glib/nm-client.c
+@@ -1116,6 +1116,11 @@ proxy_name_owner_changed (DBusGProxy *proxy,
+ priv->wimax_hw_enabled = FALSE;
+ g_free (priv->version);
+ priv->version = NULL;
++
++ /* Clear object cache to ensure bad refcounting by clients doesn't
++ * keep objects in the cache.
++ */
++ _nm_object_cache_clear (NM_OBJECT (client));
+ } else {
+ _nm_object_suppress_property_updates (NM_OBJECT (client), FALSE);
+ _nm_object_reload_properties_async (NM_OBJECT (client), updated_properties, client);
+diff --git a/libnm-glib/nm-object-cache.c b/libnm-glib/nm-object-cache.c
+index 741f129..2748b1d 100644
+--- a/libnm-glib/nm-object-cache.c
++++ b/libnm-glib/nm-object-cache.c
+@@ -64,3 +64,28 @@ _nm_object_cache_get (const char *path)
+ return object ? g_object_ref (object) : NULL;
+ }
+
++void
++_nm_object_cache_clear (NMObject *except)
++{
++ GHashTableIter iter;
++ NMObject *obj;
++ const char *path;
++ char *foo;
++
++ _init_cache ();
++ g_hash_table_iter_init (&iter, cache);
++ while (g_hash_table_iter_next (&iter, (gpointer) &path, (gpointer) &obj)) {
++ if (obj != except) {
++ /* Remove the callback so that if the object isn't yet released
++ * by a client, when it does finally get unrefed, it won't trigger
++ * the cache removal for a new object with the same path as the
++ * one being released.
++ */
++ foo = g_object_steal_data (G_OBJECT (obj), "nm-object-cache-tag");
++ g_free (foo);
++
++ g_hash_table_iter_remove (&iter);
++ }
++ }
++}
++
+diff --git a/libnm-glib/nm-object-cache.h b/libnm-glib/nm-object-cache.h
+index 8386591..8475213 100644
+--- a/libnm-glib/nm-object-cache.h
++++ b/libnm-glib/nm-object-cache.h
+@@ -32,6 +32,7 @@ G_BEGIN_DECLS
+ /* Returns referenced object from the cache */
+ NMObject *_nm_object_cache_get (const char *path);
+ void _nm_object_cache_add (NMObject *object);
++void _nm_object_cache_clear (NMObject *except);
+
+ G_END_DECLS
+
diff --git a/debian/patches/series b/debian/patches/series
index 8cac690..7129497 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -9,3 +9,6 @@
15-ignore-cached-cloned-routes-ipv6-config.patch
16-ignore-cached-cloned-routes-kernel-notifications.patch
17-dbus-remove-max_replies_per_connection-limit.patch
+18-libnm-glib-NULL-out-priv-fields-on-dispose.patch
+19-libnm-glib-discard-devices-and-active-connections-on-stop.patch
+20-libnm-glib-clear-object-cache-on-stop.patch
Reply to: