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 <od...@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