aboutsummaryrefslogtreecommitdiff
path: root/qom
diff options
context:
space:
mode:
authorThomas Huth <thuth@redhat.com>2018-07-16 14:59:18 +0200
committerPeter Maydell <peter.maydell@linaro.org>2018-07-17 13:12:49 +0100
commit0210b39d0e84d5a63a3e468f177c07a3a98d88a8 (patch)
tree8acaf4927bd6987ef245c7a3c35214bfac9a860c /qom
parent3e86907c822c0d7e6f9a4476a5b234a60f6adcf2 (diff)
qom/object: Add a new function object_initialize_child()
A lot of code is using the object_initialize() function followed by a call to object_property_add_child() to add the newly initialized object as a child of the current object. Both functions increase the reference counter of the new object, but many spots that call these two functions then forget to drop one of the superfluous references. So the newly created object is often not cleaned up correctly when the parent is destroyed. In the worst case, this can cause crashes, e.g. because device objects are not correctly removed from their parent_bus. Since this is a common pattern between many code spots, let's introduce a new function that takes care of calling all three required initialization functions, first object_initialize(), then object_property_add_child() and finally object_unref(). And since the function does a similar job like object_new_with_props(), also allow to set additional properties via varargs, and use user_creatable_complete() to make sure that the functions can be used similarly. And while we're at object.h, also fix some copy-n-paste errors in the comments there ("to store the area" --> "to store the error"). Signed-off-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Message-id: 1531745974-17187-2-git-send-email-thuth@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'qom')
-rw-r--r--qom/object.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/qom/object.c b/qom/object.c
index 4609e34a6a..75d1d48944 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -392,6 +392,60 @@ void object_initialize(void *data, size_t size, const char *typename)
object_initialize_with_type(data, size, type);
}
+void object_initialize_child(Object *parentobj, const char *propname,
+ void *childobj, size_t size, const char *type,
+ Error **errp, ...)
+{
+ va_list vargs;
+
+ va_start(vargs, errp);
+ object_initialize_childv(parentobj, propname, childobj, size, type, errp,
+ vargs);
+ va_end(vargs);
+}
+
+void object_initialize_childv(Object *parentobj, const char *propname,
+ void *childobj, size_t size, const char *type,
+ Error **errp, va_list vargs)
+{
+ Error *local_err = NULL;
+ Object *obj;
+
+ object_initialize(childobj, size, type);
+ obj = OBJECT(childobj);
+
+ object_set_propv(obj, &local_err, vargs);
+ if (local_err) {
+ goto out;
+ }
+
+ object_property_add_child(parentobj, propname, obj, &local_err);
+ if (local_err) {
+ goto out;
+ }
+
+ if (object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
+ user_creatable_complete(obj, &local_err);
+ if (local_err) {
+ object_unparent(obj);
+ goto out;
+ }
+ }
+
+ /*
+ * Since object_property_add_child added a reference to the child object,
+ * we can drop the reference added by object_initialize(), so the child
+ * property will own the only reference to the object.
+ */
+ object_unref(obj);
+
+out:
+ if (local_err) {
+ error_propagate(errp, local_err);
+ object_unref(obj);
+ }
+}
+
static inline bool object_property_is_child(ObjectProperty *prop)
{
return strstart(prop->type, "child<", NULL);