You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-18 14:21:41 +00:00
Fix regression in mechanism to hold objects while emitting
This commit is contained in:
@@ -1235,10 +1235,6 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
|
|||||||
return ERR_UNAVAILABLE;
|
return ERR_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a ref-counted object, prevent it from being destroyed during signal emission,
|
|
||||||
// which is needed in certain edge cases; e.g., https://github.com/godotengine/godot/issues/73889.
|
|
||||||
Ref<RefCounted> rc = Ref<RefCounted>(Object::cast_to<RefCounted>(this));
|
|
||||||
|
|
||||||
if (s->slot_map.size() > MAX_SLOTS_ON_STACK) {
|
if (s->slot_map.size() > MAX_SLOTS_ON_STACK) {
|
||||||
slot_callables = (Callable *)memalloc(sizeof(Callable) * s->slot_map.size());
|
slot_callables = (Callable *)memalloc(sizeof(Callable) * s->slot_map.size());
|
||||||
slot_flags = (uint32_t *)memalloc(sizeof(uint32_t) * s->slot_map.size());
|
slot_flags = (uint32_t *)memalloc(sizeof(uint32_t) * s->slot_map.size());
|
||||||
@@ -1271,6 +1267,13 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
|
|||||||
|
|
||||||
OBJ_DEBUG_LOCK
|
OBJ_DEBUG_LOCK
|
||||||
|
|
||||||
|
// If this is a ref-counted object, prevent it from being destroyed during signal
|
||||||
|
// emission, which is needed in certain edge cases; e.g., GH-73889 and GH-109471.
|
||||||
|
// Moreover, since signals can be emitted from constructors (classic example being
|
||||||
|
// notify_property_list_changed), we must be careful not to do the ref init ourselves,
|
||||||
|
// which would lead to the object being destroyed at the end of this function.
|
||||||
|
bool pending_unref = Object::cast_to<RefCounted>(this) ? ((RefCounted *)this)->reference() : false;
|
||||||
|
|
||||||
Error err = OK;
|
Error err = OK;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < slot_count; ++i) {
|
for (uint32_t i = 0; i < slot_count; ++i) {
|
||||||
@@ -1320,6 +1323,15 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
|
|||||||
memfree(slot_flags);
|
memfree(slot_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pending_unref) {
|
||||||
|
// We have to do the same Ref<T> would do. We can't just use Ref<T>
|
||||||
|
// because it would do the init ref logic, which is something this function
|
||||||
|
// shouldn't do, as explained above.
|
||||||
|
if (((RefCounted *)this)->unreference()) {
|
||||||
|
memdelete(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user