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.
This commit is contained in:
Dan Winship 2012-12-03 14:41:28 -05:00
parent 445e8755bc
commit 829234fd8d

View file

@ -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;