From 302c9fcbccf3ad945afbc3f58e42013045c6e352 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 13 Jul 2009 19:40:39 -0400 Subject: [PATCH] netlink: fix race that caused stale carrier state signals Found by Ricardo Salveti de Araujo The link cache was updated immediately, but the carrier state signals were emitted a lot later, when the cache data was already stale. So just update the cache at the same time we emit the signals. The carrier-state-request stuff wasn't originally converted to deferred for any netlink-specific reason, just to smooth the initial device creation process in NM. --- src/nm-netlink-monitor.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/nm-netlink-monitor.c b/src/nm-netlink-monitor.c index 34f873bbc..63d23d253 100644 --- a/src/nm-netlink-monitor.c +++ b/src/nm-netlink-monitor.c @@ -399,8 +399,18 @@ deferred_emit_carrier_state (gpointer user_data) priv->request_status_id = 0; - /* Emit each device's new state */ - nl_cache_foreach_filter (priv->nlh_link_cache, NULL, netlink_object_message_handler, monitor); + /* Update the link cache with latest state, and if there are no errors + * emit the link states for all the interfaces in the cache. + */ + if (nl_cache_refill (priv->nlh, priv->nlh_link_cache)) + nm_warning ("error updating link cache: %s", nl_geterror ()); + else { + nl_cache_foreach_filter (priv->nlh_link_cache, + NULL, + netlink_object_message_handler, + monitor); + } + return FALSE; } @@ -415,15 +425,6 @@ nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor, priv = NM_NETLINK_MONITOR_GET_PRIVATE (monitor); g_return_val_if_fail (priv->event_id > 0, FALSE); - /* Update the link cache with latest state */ - if (nl_cache_refill (priv->nlh, priv->nlh_link_cache)) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE, - _("error updating link cache: %s"), - nl_geterror ()); - return FALSE; - } - /* Schedule the carrier state emission */ if (!priv->request_status_id) priv->request_status_id = g_idle_add (deferred_emit_carrier_state, monitor);