From 829234fd8d79bc3cae14022c9c56d0141869ecd3 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 3 Dec 2012 14:41:28 -0500 Subject: [PATCH] libnm-glib: more NMDevice::state-changed fixes Ensure that NMDevice::state-changed signals don't get emitted out of order, and ensure that nm_device_get_state() from a ::state-changed handler always returns new_state. --- libnm-glib/nm-device.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index 46a5d97b5b..22e2844cfc 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -80,6 +80,7 @@ typedef struct { NMIP6Config *ip6_config; NMDHCP6Config *dhcp6_config; NMDeviceState state; + NMDeviceState last_seen_state; NMDeviceStateReason reason; NMActiveConnection *active_connection; @@ -197,10 +198,24 @@ device_state_change_reloaded (GObject *object, gpointer user_data) { NMDevice *self = NM_DEVICE (object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); StateChangeData *data = user_data; _nm_object_reload_properties_finish (NM_OBJECT (object), result, NULL); + /* If the device changes state several times in rapid succession, then we'll + * queue several reload_properties() calls, and there's no guarantee that + * they'll finish in the right order. In that case, only emit the signal + * for the last one. + */ + if (priv->last_seen_state != data->new_state) + return; + + /* Ensure that nm_device_get_state() will return the right value even if + * we haven't processed the corresponding PropertiesChanged yet. + */ + priv->state = data->new_state; + g_signal_emit (self, signals[STATE_CHANGED], 0, data->new_state, data->old_state, data->reason); g_slice_free (StateChangeData, data); @@ -213,6 +228,9 @@ device_state_changed (DBusGProxy *proxy, NMDeviceStateReason reason, gpointer user_data) { + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + if (old_state != new_state) { StateChangeData *data; @@ -221,6 +239,8 @@ device_state_changed (DBusGProxy *proxy, * in the process of asynchronously reading the new values. * Wait for that to finish before emitting the signal. */ + priv->last_seen_state = new_state; + data = g_slice_new (StateChangeData); data->old_state = old_state; data->new_state = new_state;