core: fix wrongly exporting object before instance is fully constructed

Exporting the object already in the *_init() function will later
break because the object is not yet fully initialized at that point.

Add a convenient flag so that the NMExportedObject parent implementation
automatically can export itself. This saves the derived class from
overwriting the constructed() method.

Also add an assertion to catch such bugs.
This commit is contained in:
Thomas Haller
2015-11-04 14:44:29 +01:00
parent ae5cfba05c
commit 8a8ecc46ca
4 changed files with 33 additions and 4 deletions

View File

@@ -104,8 +104,6 @@ nm_dhcp4_config_init (NMDhcp4Config *self)
{ {
NMDhcp4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (self); NMDhcp4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (self);
nm_exported_object_export (NM_EXPORTED_OBJECT (self));
priv->options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); priv->options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
g_variant_ref_sink (priv->options); g_variant_ref_sink (priv->options);
} }
@@ -145,6 +143,7 @@ nm_dhcp4_config_class_init (NMDhcp4ConfigClass *config_class)
g_type_class_add_private (config_class, sizeof (NMDhcp4ConfigPrivate)); g_type_class_add_private (config_class, sizeof (NMDhcp4ConfigPrivate));
exported_object_class->export_path = NM_DBUS_PATH "/DHCP4Config/%u"; exported_object_class->export_path = NM_DBUS_PATH "/DHCP4Config/%u";
exported_object_class->export_on_construction = TRUE;
/* virtual methods */ /* virtual methods */
object_class->get_property = get_property; object_class->get_property = get_property;

View File

@@ -104,8 +104,6 @@ nm_dhcp6_config_init (NMDhcp6Config *self)
{ {
NMDhcp6ConfigPrivate *priv = NM_DHCP6_CONFIG_GET_PRIVATE (self); NMDhcp6ConfigPrivate *priv = NM_DHCP6_CONFIG_GET_PRIVATE (self);
nm_exported_object_export (NM_EXPORTED_OBJECT (self));
priv->options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); priv->options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
g_variant_ref_sink (priv->options); g_variant_ref_sink (priv->options);
} }
@@ -145,6 +143,7 @@ nm_dhcp6_config_class_init (NMDhcp6ConfigClass *config_class)
g_type_class_add_private (config_class, sizeof (NMDhcp6ConfigPrivate)); g_type_class_add_private (config_class, sizeof (NMDhcp6ConfigPrivate));
exported_object_class->export_path = NM_DBUS_PATH "/DHCP6Config/%u"; exported_object_class->export_path = NM_DBUS_PATH "/DHCP6Config/%u";
exported_object_class->export_on_construction = TRUE;
/* virtual methods */ /* virtual methods */
object_class->get_property = get_property; object_class->get_property = get_property;

View File

@@ -29,6 +29,10 @@
static GHashTable *prefix_counters; static GHashTable *prefix_counters;
#if NM_MORE_ASSERTS >= 2
#define _ASSERT_NO_EARLY_EXPORT
#endif
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMExportedObject, nm_exported_object, G_TYPE_OBJECT, G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMExportedObject, nm_exported_object, G_TYPE_OBJECT,
prefix_counters = g_hash_table_new (g_str_hash, g_str_equal); prefix_counters = g_hash_table_new (g_str_hash, g_str_equal);
) )
@@ -41,6 +45,10 @@ typedef struct {
GVariantBuilder pending_notifies; GVariantBuilder pending_notifies;
guint notify_idle_id; guint notify_idle_id;
#ifdef _ASSERT_NO_EARLY_EXPORT
gboolean _constructed;
#endif
} NMExportedObjectPrivate; } NMExportedObjectPrivate;
#define NM_EXPORTED_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_EXPORTED_OBJECT, NMExportedObjectPrivate)) #define NM_EXPORTED_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_EXPORTED_OBJECT, NMExportedObjectPrivate))
@@ -490,6 +498,10 @@ nm_exported_object_export (NMExportedObject *self)
g_return_val_if_fail (!priv->path, priv->path); g_return_val_if_fail (!priv->path, priv->path);
g_return_val_if_fail (!priv->bus_mgr, NULL); g_return_val_if_fail (!priv->bus_mgr, NULL);
#ifdef _ASSERT_NO_EARLY_EXPORT
nm_assert (priv->_constructed);
#endif
class_export_path = NM_EXPORTED_OBJECT_GET_CLASS (self)->export_path; class_export_path = NM_EXPORTED_OBJECT_GET_CLASS (self)->export_path;
p = strchr (class_export_path, '%'); p = strchr (class_export_path, '%');
if (p) { if (p) {
@@ -731,6 +743,23 @@ nm_exported_object_notify (GObject *object, GParamSpec *pspec)
priv->notify_idle_id = g_idle_add (idle_emit_properties_changed, object); priv->notify_idle_id = g_idle_add (idle_emit_properties_changed, object);
} }
static void
constructed (GObject *object)
{
NMExportedObjectClass *klass;
G_OBJECT_CLASS (nm_exported_object_parent_class)->constructed (object);
#ifdef _ASSERT_NO_EARLY_EXPORT
NM_EXPORTED_OBJECT_GET_PRIVATE (object)->_constructed = TRUE;
#endif
klass = NM_EXPORTED_OBJECT_GET_CLASS (object);
if (klass->export_on_construction)
nm_exported_object_export ((NMExportedObject *) object);
}
static void static void
nm_exported_object_dispose (GObject *object) nm_exported_object_dispose (GObject *object)
{ {
@@ -752,6 +781,7 @@ nm_exported_object_class_init (NMExportedObjectClass *klass)
g_type_class_add_private (object_class, sizeof (NMExportedObjectPrivate)); g_type_class_add_private (object_class, sizeof (NMExportedObjectPrivate));
object_class->constructed = constructed;
object_class->notify = nm_exported_object_notify; object_class->notify = nm_exported_object_notify;
object_class->dispose = nm_exported_object_dispose; object_class->dispose = nm_exported_object_dispose;
} }

View File

@@ -40,6 +40,7 @@ typedef struct {
GObjectClass parent; GObjectClass parent;
const char *export_path; const char *export_path;
char export_on_construction;
} NMExportedObjectClass; } NMExportedObjectClass;
GType nm_exported_object_get_type (void); GType nm_exported_object_get_type (void);