diff options
author | Thomas Haller <thaller@redhat.com> | 2017-03-15 10:40:17 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-03-15 10:40:17 +0100 |
commit | 7cb3928c499c0a5a7d70a03c93256540dea47321 (patch) | |
tree | 9a8302c7617cb056c9e49e450d28cde9224b2389 | |
parent | 22b7282d843f24442aed6a72617e0038f572b2c9 (diff) | |
parent | c8934fbe0df0459508a47dfd33b35e9e27dbc77b (diff) | |
download | NetworkManager-7cb3928c499c0a5a7d70a03c93256540dea47321.tar.gz |
core: merge branch 'th/startup-complete-race-bgo779920'
https://bugzilla.gnome.org/show_bug.cgi?id=779920
-rw-r--r-- | src/devices/nm-device.c | 46 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/nm-manager.c | 70 |
3 files changed, 85 insertions, 33 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index cfa91951a0..5857b8f84c 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -10645,6 +10645,8 @@ _set_unmanaged_flags (NMDevice *self, const char *operation = NULL; char str1[512]; char str2[512]; + gboolean do_notify_has_pending_actions = FALSE; + gboolean had_pending_actions = FALSE; g_return_if_fail (NM_IS_DEVICE (self)); g_return_if_fail (flags); @@ -10680,6 +10682,11 @@ _set_unmanaged_flags (NMDevice *self, nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id)); priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); } + + if (!priv->pending_actions) { + do_notify_has_pending_actions = TRUE; + had_pending_actions = nm_device_has_pending_action (self); + } } old_flags = priv->unmanaged_flags; @@ -10715,19 +10722,16 @@ _set_unmanaged_flags (NMDevice *self, || ( !was_managed && nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED)); -#define _FMTX "[%s%s0x%0x/0x%x/%s" -#define _FMT(flags, mask, str) \ - _unmanaged_flags2str ((flags), (mask), str, sizeof (str)), \ - ((flags) | (mask)) ? "=" : "", \ - (flags), \ - (mask), \ - (_get_managed_by_flags (flags, mask, FALSE) \ - ? "managed" \ - : (_get_managed_by_flags (flags, mask, TRUE) \ - ? "manageable" \ - : "unmanaged")) - _LOGD (LOGD_DEVICE, "unmanaged: flags set to "_FMTX"%s, %s [%s=0x%0x]%s%s%s)", - _FMT (priv->unmanaged_flags, priv->unmanaged_mask, str1), + _LOGD (LOGD_DEVICE, "unmanaged: flags set to [%s%s0x%0x/0x%x/%s%s], %s [%s=0x%0x]%s%s%s)", + _unmanaged_flags2str (priv->unmanaged_flags, priv->unmanaged_mask, str1, sizeof (str1)), \ + (priv->unmanaged_flags | priv->unmanaged_mask) ? "=" : "", \ + (guint) priv->unmanaged_flags, \ + (guint) priv->unmanaged_mask, \ + (_get_managed_by_flags (priv->unmanaged_flags, priv->unmanaged_mask, FALSE) \ + ? "managed" \ + : (_get_managed_by_flags (priv->unmanaged_flags, priv->unmanaged_mask, TRUE) \ + ? "manageable" \ + : "unmanaged")), priv->real ? "" : "/unrealized", operation, nm_unmanaged_flags2str (flags, str2, sizeof (str2)), @@ -10737,7 +10741,10 @@ _set_unmanaged_flags (NMDevice *self, reason_to_string (reason), transition_state ? ", transition-state" : "", "")); -#undef _FMT + + if ( do_notify_has_pending_actions + && had_pending_actions != nm_device_has_pending_action (self)) + _notify (self, PROP_HAS_PENDING_ACTION); if (transition_state) { new_state = was_managed ? NM_DEVICE_STATE_UNMANAGED : NM_DEVICE_STATE_UNAVAILABLE; @@ -11412,7 +11419,16 @@ nm_device_has_pending_action (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - return !!priv->pending_actions; + if (priv->pending_actions) + return TRUE; + + if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) { + /* as long as the platform link is not yet initialized, we have a pending + * action. */ + return TRUE; + } + + return FALSE; } /*****************************************************************************/ diff --git a/src/main.c b/src/main.c index 157bec2093..23c05f2952 100644 --- a/src/main.c +++ b/src/main.c @@ -402,6 +402,8 @@ main (int argc, char *argv[]) goto done; } + nm_platform_process_events (NM_PLATFORM_GET); + /* Make sure the loopback interface is up. If interface is down, we bring * it up and kernel will assign it link-local IPv4 and IPv6 addresses. If * it was already up, we assume is in clean state. diff --git a/src/nm-manager.c b/src/nm-manager.c index df7b8eb33a..5b9b144891 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -86,6 +86,10 @@ static void device_sleep_cb (NMDevice *device, GParamSpec *pspec, NMManager *self); +static void settings_startup_complete_changed (NMSettings *settings, + GParamSpec *pspec, + NMManager *self); + static NM_CACHED_QUARK_FCN ("active-connection-add-and-activate", active_connection_add_and_activate_quark) typedef struct { @@ -129,9 +133,6 @@ typedef struct { char *hostname; RadioState radio_states[RFKILL_TYPE_MAX]; - gboolean sleeping; - gboolean net_enabled; - NMVpnManager *vpn_manager; NMSleepMonitor *sleep_monitor; @@ -147,8 +148,14 @@ typedef struct { guint timestamp_update_id; - gboolean startup; - gboolean devices_inited; + guint devices_inited_id; + + bool startup:1; + bool devices_inited:1; + bool devices_inited_ready:1; + + bool sleeping:1; + bool net_enabled:1; } NMManagerPrivate; struct _NMManager { @@ -937,15 +944,18 @@ check_if_startup_complete (NMManager *self) _LOGI (LOGD_CORE, "startup complete"); priv->startup = FALSE; - _notify (self, PROP_STARTUP); - /* We don't have to watch notify::has-pending-action any more. */ + /* we no longer care about these signals. Startup-complete only + * happens once. */ + g_signal_handlers_disconnect_by_func (priv->settings, G_CALLBACK (settings_startup_complete_changed), self); for (iter = priv->devices; iter; iter = iter->next) { - NMDevice *dev = iter->data; - - g_signal_handlers_disconnect_by_func (dev, G_CALLBACK (device_has_pending_action_changed), self); + g_signal_handlers_disconnect_by_func (iter->data, + G_CALLBACK (device_has_pending_action_changed), + self); } + _notify (self, PROP_STARTUP); + if (nm_config_get_configure_and_quit (priv->config)) g_signal_emit (self, signals[CONFIGURE_QUIT], 0); } @@ -4804,6 +4814,25 @@ nm_manager_write_device_state (NMManager *self) seen_ifindexes); } +static gboolean +devices_inited_cb (gpointer user_data) +{ + NMManager *self = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + + if (!priv->devices_inited_ready) { + /* lets go through another idle invocation to give the system + * more time to settle. */ + priv->devices_inited_ready = TRUE; + return G_SOURCE_CONTINUE; + } + + priv->devices_inited_id = 0; + priv->devices_inited = TRUE; + check_if_startup_complete (self); + return G_SOURCE_REMOVE; +} + gboolean nm_manager_start (NMManager *self, GError **error) { @@ -4814,11 +4843,6 @@ nm_manager_start (NMManager *self, GError **error) if (!nm_settings_start (priv->settings, error)) return FALSE; - g_signal_connect (NM_PLATFORM_GET, - NM_PLATFORM_SIGNAL_LINK_CHANGED, - G_CALLBACK (platform_link_cb), - self); - /* Set initial radio enabled/disabled state */ for (i = 0; i < RFKILL_TYPE_MAX; i++) { RadioState *rstate = &priv->radio_states[i]; @@ -4851,6 +4875,13 @@ nm_manager_start (NMManager *self, GError **error) nm_device_factory_manager_load_factories (_register_device_factory, self); nm_device_factory_manager_for_each_factory (start_factory, NULL); + nm_platform_process_events (NM_PLATFORM_GET); + + g_signal_connect (NM_PLATFORM_GET, + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK (platform_link_cb), + self); + platform_query_devices (self); /* Load VPN plugins */ @@ -4864,9 +4895,8 @@ nm_manager_start (NMManager *self, GError **error) for (i = 0; connections[i]; i++) connection_changed (self, NM_CONNECTION (connections[i])); - priv->devices_inited = TRUE; - - check_if_startup_complete (self); + nm_clear_g_source (&priv->devices_inited_id); + priv->devices_inited_id = g_idle_add_full (G_PRIORITY_LOW + 10, devices_inited_cb, self, NULL); return TRUE; } @@ -4881,6 +4911,8 @@ nm_manager_stop (NMManager *self) remove_device (self, NM_DEVICE (priv->devices->data), TRUE, TRUE); _active_connection_cleanup (self); + + nm_clear_g_source (&priv->devices_inited_id); } static gboolean @@ -6039,6 +6071,8 @@ dispose (GObject *object) g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref); priv->auth_chains = NULL; + nm_clear_g_source (&priv->devices_inited_id); + if (priv->checkpoint_mgr) { nm_checkpoint_manager_destroy_all (priv->checkpoint_mgr, NULL); g_clear_pointer (&priv->checkpoint_mgr, nm_checkpoint_manager_unref); |