aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/core/qdev.c17
-rw-r--r--include/hw/qdev-core.h1
2 files changed, 15 insertions, 3 deletions
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 606ab53c42..0019a49503 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -928,6 +928,13 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
goto post_realize_fail;
}
+ /*
+ * always free/re-initialize here since the value cannot be cleaned up
+ * in device_unrealize due to its usage later on in the unplug path
+ */
+ g_free(dev->canonical_path);
+ dev->canonical_path = object_get_canonical_path(OBJECT(dev));
+
if (qdev_get_vmsd(dev)) {
if (vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
dev->instance_id_alias,
@@ -984,6 +991,8 @@ child_realize_fail:
}
post_realize_fail:
+ g_free(dev->canonical_path);
+ dev->canonical_path = NULL;
if (dc->unrealize) {
dc->unrealize(dev, NULL);
}
@@ -1102,10 +1111,12 @@ static void device_unparent(Object *obj)
/* Only send event if the device had been completely realized */
if (dev->pending_deleted_event) {
- gchar *path = object_get_canonical_path(OBJECT(dev));
+ g_assert(dev->canonical_path);
- qapi_event_send_device_deleted(!!dev->id, dev->id, path, &error_abort);
- g_free(path);
+ qapi_event_send_device_deleted(!!dev->id, dev->id, dev->canonical_path,
+ &error_abort);
+ g_free(dev->canonical_path);
+ dev->canonical_path = NULL;
}
qemu_opts_del(dev->opts);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 089146197f..0a71bf83f0 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -153,6 +153,7 @@ struct DeviceState {
/*< public >*/
const char *id;
+ char *canonical_path;
bool realized;
bool pending_deleted_event;
QemuOpts *opts;