diff --git a/ChangeLog b/ChangeLog index 8a7c2e5069..d1bc5fa2cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-05-14 Dan Williams + + Fix Linus' bug in rh #134886 + + * src/nm-device-802-3-ethernet.c + - (constructor): request initial carrier state + + * src/nm-netlink-monitor.c + - (nm_netlink_monitor_request_status): schedule emission of carrier + signals after refilling the link cache. Because the refill is a + synchronous operation, the normal message hander won't get called + since libnl has already consumed the messages. + - (deferred_emit_carrier_state): emit carrier states from an idle handler + 2008-05-14 Dan Williams * src/NetworkManagerSystem.c diff --git a/src/nm-device-802-3-ethernet.c b/src/nm-device-802-3-ethernet.c index 6a22ffe36e..4c3371ed29 100644 --- a/src/nm-device-802-3-ethernet.c +++ b/src/nm-device-802-3-ethernet.c @@ -274,6 +274,8 @@ constructor (GType type, caps = nm_device_get_capabilities (dev); if (caps & NM_DEVICE_CAP_CARRIER_DETECT) { + GError *error = NULL; + /* Only listen to netlink for cards that support carrier detect */ NMNetlinkMonitor * monitor = nm_netlink_monitor_get (); @@ -284,6 +286,11 @@ constructor (GType type, G_CALLBACK (nm_device_802_3_ethernet_carrier_off), dev); + if (!nm_netlink_monitor_request_status (monitor, &error)) { + nm_warning ("couldn't request carrier state: %s", error->message); + g_error_free (error); + } + g_object_unref (monitor); } else { priv->link_connected_id = 0; diff --git a/src/nm-netlink-monitor.c b/src/nm-netlink-monitor.c index 4cfcb7e24a..b141a98069 100644 --- a/src/nm-netlink-monitor.c +++ b/src/nm-netlink-monitor.c @@ -66,6 +66,8 @@ typedef struct { GMainContext * context; GIOChannel * io_channel; GSource * event_source; + + guint request_status_id; } NMNetlinkMonitorPrivate; static gboolean nm_netlink_monitor_event_handler (GIOChannel *channel, @@ -115,6 +117,9 @@ finalize (GObject *object) { NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (object); + if (priv->request_status_id) + g_source_remove (priv->request_status_id); + if (priv->io_channel) nm_netlink_monitor_close_connection (NM_NETLINK_MONITOR (object)); @@ -403,6 +408,19 @@ nm_netlink_monitor_detach (NMNetlinkMonitor *monitor) priv->context = NULL; } +static gboolean +deferred_emit_carrier_state (gpointer user_data) +{ + NMNetlinkMonitor *monitor = NM_NETLINK_MONITOR (user_data); + NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (monitor); + + 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); + return FALSE; +} + gboolean nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor, GError **error) @@ -414,11 +432,16 @@ nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor, priv = NM_NETLINK_MONITOR_GET_PRIVATE (monitor); g_return_val_if_fail (priv->context != NULL, FALSE); + /* Update the link cache with latest state */ if (nl_cache_refill (priv->nlh, priv->nlh_link_cache)) { nm_warning ("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); + return TRUE; }