The next change adds code to retain references from an object to the
parent when it is being unparented to ensure that the parent outlive
them. This change handles the following scenario with the code:
1. The parent starts being finalized without unparenting.
2. Unparenting happens during finalization.
3. The child retains the reference to the parent.
4. The child gets finalized, and releases the reference.
In this scenario, the reference counter of the parent reaches to zero,
gets incremented, and gets decremented to reach to zero again. This
change ensures that finalization will be triggered again in the
scenario.
Note that the reference counter needs to reach to zero again before
finalization ends; otherwise the object will be "resurrected", which
is not clearly defined and prohibited with an existing assertion.
One thing that looks concerning with this change is that it adds a bool
to Object. This is not a problem in the most situations where the host
uses 64-bit addressing because the member is added to a gap needed for
alignment, and possible double-free scenarios handled with this change
are more serious than the extra memory usage for 32-bit hosts.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
---
include/qom/object.h | 1 +
qom/object.c | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/include/qom/object.h b/include/qom/object.h
index 26df6137b911..7f7b1ffea8fe 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -158,6 +158,7 @@ struct Object
ObjectFree *free;
GHashTable *properties;
uint32_t ref;
+ bool finalizing;
Object *parent;
};
diff --git a/qom/object.c b/qom/object.c
index 1856bb36c74c..b766b2e9baa7 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -725,6 +725,11 @@ static void object_finalize(void *data)
Object *obj = data;
TypeImpl *ti = obj->class->type;
+ if (obj->finalizing) {
+ return;
+ }
+
+ obj->finalizing = true;
object_property_del_all(obj);
object_deinit(obj, ti);
--
2.51.0