From patchwork Thu Jul 12 15:30:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 943088 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41RKhd1Yybz9rxs for ; Fri, 13 Jul 2018 01:33:21 +1000 (AEST) Received: from localhost ([::1]:60777 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fddao-0006F1-Oy for incoming@patchwork.ozlabs.org; Thu, 12 Jul 2018 11:33:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37597) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fddYq-0005Kr-4k for qemu-devel@nongnu.org; Thu, 12 Jul 2018 11:31:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fddYl-0007st-Uz for qemu-devel@nongnu.org; Thu, 12 Jul 2018 11:31:16 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38062 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fddYi-0007n5-LE; Thu, 12 Jul 2018 11:31:08 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4231EC32E; Thu, 12 Jul 2018 15:31:08 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-19.ams2.redhat.com [10.36.116.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 956A31C66C; Thu, 12 Jul 2018 15:31:06 +0000 (UTC) From: Thomas Huth To: qemu-devel@nongnu.org, Peter Maydell , Paolo Bonzini Date: Thu, 12 Jul 2018 17:30:59 +0200 Message-Id: <1531409463-3843-2-git-send-email-thuth@redhat.com> In-Reply-To: <1531409463-3843-1-git-send-email-thuth@redhat.com> References: <1531409463-3843-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Thu, 12 Jul 2018 15:31:08 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Thu, 12 Jul 2018 15:31:08 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH 1/5] qom/object: Add a new function object_initialize_as_child() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org, Markus Armbruster , Eduardo Habkost Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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 introdcue 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(). Signed-off-by: Thomas Huth --- include/qom/object.h | 19 +++++++++++++++++++ qom/object.c | 14 ++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/qom/object.h b/include/qom/object.h index f3d2308..c1b254c 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -749,6 +749,25 @@ int object_set_propv(Object *obj, void object_initialize(void *obj, size_t size, const char *typename); /** + * object_initialize_as_child: + * @parentobj: The parent object to add a property to + * @propname: The name of the property + * @childobj: A pointer to the memory to be used for the object. + * @size: The maximum size available at @obj for the object. + * @type: The name of the type of the object to instantiate. + * @errp: If an error occurs, a pointer to an area to store the area + * + * This function will initialize an object. The memory for the object should + * have already been allocated. The object will then be added as child property + * to a parent with object_property_add_child() function. The returned object + * has a reference count of 1, and will be finalized when the last reference is + * dropped. + */ +void object_initialize_as_child(Object *parentobj, const char *propname, + void *childobj, size_t size, const char *type, + Error **errp); + +/** * object_dynamic_cast: * @obj: The object to cast. * @typename: The @typename to cast to. diff --git a/qom/object.c b/qom/object.c index 4609e34..de2ded0 100644 --- a/qom/object.c +++ b/qom/object.c @@ -392,6 +392,20 @@ void object_initialize(void *data, size_t size, const char *typename) object_initialize_with_type(data, size, type); } +void object_initialize_as_child(Object *parentobj, const char *propname, + void *childobj, size_t size, const char *type, + Error **errp) +{ + object_initialize(childobj, size, type); + object_property_add_child(parentobj, propname, OBJECT(childobj), errp); + /* + * Since object_property_add_child added a reference to the child object, + * we can drop the initial reference from object_initialize now. + */ + object_unref(OBJECT(childobj)); +} + + static inline bool object_property_is_child(ObjectProperty *prop) { return strstart(prop->type, "child<", NULL);