mirror of https://gitee.com/openkylin/qemu.git
qdev: Fix object reference leak in case device.realize() fails
If device doesn't have parent assined before its realize is called, device_set_realized() will implicitly set parent to '/machine/unattached'. However device_set_realized() may fail after that point at several other points leaving not realized object dangling in '/machine/unattached' and as result caller of obj = object_new() obj->ref == 1 object_property_set_bool(obj,..., true, "realized",...) obj->ref == 2 if (fail) object_unref(obj); obj->ref == 1 will get object leak instead of expected object destruction. Fix it by making device_set_realized() to cleanup after itself in case of failure. Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
a07f953ef4
commit
69382d8b3e
|
@ -885,6 +885,8 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
||||||
HotplugHandler *hotplug_ctrl;
|
HotplugHandler *hotplug_ctrl;
|
||||||
BusState *bus;
|
BusState *bus;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
bool unattached_parent = false;
|
||||||
|
static int unattached_count;
|
||||||
|
|
||||||
if (dev->hotplugged && !dc->hotpluggable) {
|
if (dev->hotplugged && !dc->hotpluggable) {
|
||||||
error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
|
error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
|
||||||
|
@ -893,12 +895,12 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
||||||
|
|
||||||
if (value && !dev->realized) {
|
if (value && !dev->realized) {
|
||||||
if (!obj->parent) {
|
if (!obj->parent) {
|
||||||
static int unattached_count;
|
|
||||||
gchar *name = g_strdup_printf("device[%d]", unattached_count++);
|
gchar *name = g_strdup_printf("device[%d]", unattached_count++);
|
||||||
|
|
||||||
object_property_add_child(container_get(qdev_get_machine(),
|
object_property_add_child(container_get(qdev_get_machine(),
|
||||||
"/unattached"),
|
"/unattached"),
|
||||||
name, obj, &error_abort);
|
name, obj, &error_abort);
|
||||||
|
unattached_parent = true;
|
||||||
g_free(name);
|
g_free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,6 +989,10 @@ post_realize_fail:
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
|
if (unattached_parent) {
|
||||||
|
object_unparent(OBJECT(dev));
|
||||||
|
unattached_count--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool device_get_hotpluggable(Object *obj, Error **errp)
|
static bool device_get_hotpluggable(Object *obj, Error **errp)
|
||||||
|
|
Loading…
Reference in New Issue