Commit 4b2935b9 authored by Dan Williams's avatar Dan Williams

merge: fix libnm signal/ordering issues (bgo #738979)

parents 098d655e e5827729
......@@ -68,6 +68,12 @@
#include "nm-version.h"
#include "nm-vpn-dbus-interface.h"
#define NM_UTILS_CLEAR_CANCELLABLE(c) \
if (c) { \
g_cancellable_cancel (c); \
g_clear_object (&c); \
}
const char *_nm_setting_ip4_config_get_address_label (NMSettingIP4Config *setting,
guint32 i);
gboolean _nm_setting_ip4_config_add_address_with_label (NMSettingIP4Config *setting,
......
......@@ -275,6 +275,7 @@ device_state_changed (NMDBusDevice *proxy,
data->new_state = new_state;
data->reason = reason;
_nm_object_reload_properties_async (NM_OBJECT (user_data),
NULL,
device_state_change_reloaded,
data);
}
......
......@@ -53,6 +53,7 @@ G_DEFINE_TYPE_WITH_CODE (NMManager, nm_manager, NM_TYPE_OBJECT,
typedef struct {
NMDBusManager *manager_proxy;
GCancellable *props_cancellable;
char *version;
NMState state;
gboolean startup;
......@@ -1207,7 +1208,8 @@ updated_properties (GObject *object, GAsyncResult *result, gpointer user_data)
GError *error = NULL;
if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) {
g_warning ("%s: error reading NMManager properties: %s", __func__, error->message);
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("%s: error reading NMManager properties: %s", __func__, error->message);
g_error_free (error);
}
......@@ -1223,6 +1225,8 @@ nm_running_changed_cb (GObject *object,
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
if (!nm_manager_get_nm_running (manager)) {
NM_UTILS_CLEAR_CANCELLABLE (priv->props_cancellable);
priv->state = NM_STATE_UNKNOWN;
priv->startup = FALSE;
_nm_object_queue_notify (NM_OBJECT (manager), NM_MANAGER_NM_RUNNING);
......@@ -1246,7 +1250,11 @@ nm_running_changed_cb (GObject *object,
_nm_object_cache_clear ();
} else {
_nm_object_suppress_property_updates (NM_OBJECT (manager), FALSE);
_nm_object_reload_properties_async (NM_OBJECT (manager), updated_properties, manager);
NM_UTILS_CLEAR_CANCELLABLE (priv->props_cancellable);
priv->props_cancellable = g_cancellable_new ();
_nm_object_reload_properties_async (NM_OBJECT (manager), priv->props_cancellable, updated_properties, manager);
manager_recheck_permissions (priv->manager_proxy, manager);
}
}
......
......@@ -40,9 +40,8 @@ void _nm_object_register_properties (NMObject *object,
const char *interface,
const NMPropertiesInfo *info);
gboolean _nm_object_reload_properties (NMObject *object, GError **error);
void _nm_object_reload_properties_async (NMObject *object,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean _nm_object_reload_properties_finish (NMObject *object,
......
This diff is collapsed.
......@@ -44,6 +44,7 @@ typedef struct {
NMDBusSettings *proxy;
GPtrArray *all_connections;
GPtrArray *visible_connections;
GCancellable *props_cancellable;
/* AddConnectionInfo objects that are waiting for the connection to become initialized */
GSList *add_list;
......@@ -604,7 +605,8 @@ updated_properties (GObject *object, GAsyncResult *result, gpointer user_data)
GError *error = NULL;
if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) {
g_warning ("%s: error reading NMRemoteSettings properties: %s", __func__, error->message);
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("%s: error reading NMRemoteSettings properties: %s", __func__, error->message);
g_error_free (error);
}
}
......@@ -623,6 +625,8 @@ nm_running_changed (GObject *object,
GPtrArray *connections;
int i;
NM_UTILS_CLEAR_CANCELLABLE (priv->props_cancellable);
/* Clear connections */
connections = priv->all_connections;
priv->all_connections = g_ptr_array_new ();
......@@ -645,7 +649,10 @@ nm_running_changed (GObject *object,
_nm_object_suppress_property_updates (NM_OBJECT (self), TRUE);
} else {
_nm_object_suppress_property_updates (NM_OBJECT (self), FALSE);
_nm_object_reload_properties_async (NM_OBJECT (self), updated_properties, self);
NM_UTILS_CLEAR_CANCELLABLE (priv->props_cancellable);
priv->props_cancellable = g_cancellable_new ();
_nm_object_reload_properties_async (NM_OBJECT (self), priv->props_cancellable, updated_properties, self);
}
g_object_thaw_notify (object);
......
......@@ -111,6 +111,104 @@ test_device_added (void)
/*******************************************************************/
typedef enum {
SIGNAL_FIRST = 0x01,
SIGNAL_SECOND = 0x02,
SIGNAL_MASK = 0x0F,
NOTIFY_FIRST = 0x10,
NOTIFY_SECOND = 0x20,
NOTIFY_MASK = 0xF0
} DeviceSignaledAfterInitType;
static void
device_sai_added_cb (NMClient *c,
NMDevice *device,
gpointer user_data)
{
guint *result = user_data;
g_assert (device);
g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
g_assert ((*result & SIGNAL_MASK) == 0);
*result |= *result ? SIGNAL_SECOND : SIGNAL_FIRST;
}
static void
devices_sai_notify_cb (NMClient *c,
GParamSpec *pspec,
gpointer user_data)
{
guint *result = user_data;
const GPtrArray *devices;
NMDevice *device;
devices = nm_client_get_devices (c);
g_assert (devices);
g_assert_cmpint (devices->len, ==, 1);
device = g_ptr_array_index (devices, 0);
g_assert (device);
g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
g_assert ((*result & NOTIFY_MASK) == 0);
*result |= *result ? NOTIFY_SECOND : NOTIFY_FIRST;
}
static void
test_device_added_signal_after_init (void)
{
NMClient *client;
const GPtrArray *devices;
NMDevice *device;
guint result = 0;
GError *error = NULL;
sinfo = nm_test_service_init ();
client = nm_client_new (NULL, &error);
g_assert_no_error (error);
devices = nm_client_get_devices (client);
g_assert (devices->len == 0);
g_signal_connect (client,
NM_CLIENT_DEVICE_ADDED,
(GCallback) device_sai_added_cb,
&result);
g_signal_connect (client,
"notify::" NM_CLIENT_DEVICES,
(GCallback) devices_sai_notify_cb,
&result);
/* Tell the test service to add a new device */
nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
/* Ensure the 'device-added' signal doesn't show up before
* the 'Devices' property change notification */
while (!(result & SIGNAL_MASK) && !(result & NOTIFY_MASK))
g_main_context_iteration (NULL, TRUE);
g_signal_handlers_disconnect_by_func (client, device_sai_added_cb, &result);
g_signal_handlers_disconnect_by_func (client, devices_sai_notify_cb, &result);
g_assert ((result & NOTIFY_MASK) == NOTIFY_FIRST);
g_assert ((result & SIGNAL_MASK) == SIGNAL_SECOND);
devices = nm_client_get_devices (client);
g_assert (devices);
g_assert_cmpint (devices->len, ==, 1);
device = g_ptr_array_index (devices, 0);
g_assert (device);
g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
g_object_unref (client);
g_clear_pointer (&sinfo, nm_test_service_cleanup);
}
/*******************************************************************/
static const char *expected_bssid = "66:55:44:33:22:11";
typedef struct {
......@@ -1077,6 +1175,7 @@ main (int argc, char **argv)
loop = g_main_loop_new (NULL, FALSE);
g_test_add_func ("/libnm/device-added", test_device_added);
g_test_add_func ("/libnm/device-added-signal-after-init", test_device_added_signal_after_init);
g_test_add_func ("/libnm/wifi-ap-added-removed", test_wifi_ap_added_removed);
g_test_add_func ("/libnm/wimax-nsp-added-removed", test_wimax_nsp_added_removed);
g_test_add_func ("/libnm/devices-array", test_devices_array);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment