This needs to be carefully merged back but I'm not 100% confident the problem is solved by this commit. --- hw/pci.c | 1 + hw/qdev.c | 1 + include/qemu/object.h | 4 +++- qom/object.c | 13 ++++++++++--- 4 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/hw/pci.c b/hw/pci.c index 1df05ae..5f4f80e 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1517,6 +1517,7 @@ static int pci_unplug_device(DeviceState *qdev) qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev))); return -1; } + object_unparent(OBJECT(dev)); return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, PCI_HOTPLUG_DISABLED); } diff --git a/hw/qdev.c b/hw/qdev.c index f04f0fa..e3b53b7 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -222,6 +222,7 @@ void qbus_reset_all_fn(void *opaque) int qdev_simple_unplug_cb(DeviceState *dev) { /* just zap it */ + object_unparent(OBJECT(dev)); qdev_free(dev); return 0; } diff --git a/include/qemu/object.h b/include/qemu/object.h index b77584c..947cf29 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -524,7 +524,9 @@ void object_property_add(Object *obj, const char *name, const char *type, ObjectPropertyRelease *release, void *opaque, struct Error **errp); -void object_property_del(Object *obj, const char *name, Error **errp); +void object_property_del(Object *obj, const char *name, struct Error **errp); + +void object_unparent(Object *obj); /** * object_property_get: diff --git a/qom/object.c b/qom/object.c index 3c3c8f9..cd517f6 100644 --- a/qom/object.c +++ b/qom/object.c @@ -304,6 +304,13 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp) } } +void object_unparent(Object *obj) +{ + if (obj->parent) { + object_property_del_child(obj->parent, obj, NULL); + } +} + static void object_deinit(Object *obj, TypeImpl *type) { if (type->instance_finalize) { @@ -319,9 +326,8 @@ static void object_deinit(Object *obj, TypeImpl *type) if (type_has_parent(type)) { object_deinit(obj, type_get_parent(type)); } - if (obj->parent) { - object_property_del_child(obj->parent, obj, NULL); - } + + object_unparent(obj); } void object_finalize(void *data) @@ -557,6 +563,7 @@ void object_unref(Object *obj) g_assert(obj->ref > 0); obj->ref--; + /* parent always holds a reference to its children */ if (obj->ref == 0) { object_finalize(obj); } -- 1.7.4.1