@@ -1235,10 +1235,6 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
12351235 return ERR_UNAVAILABLE;
12361236 }
12371237
1238- // If this is a ref-counted object, prevent it from being destroyed during signal emission,
1239- // which is needed in certain edge cases; e.g., https://github.com/godotengine/godot/issues/73889.
1240- Ref<RefCounted> rc = Ref<RefCounted>(Object::cast_to<RefCounted>(this ));
1241-
12421238 if (s->slot_map .size () > MAX_SLOTS_ON_STACK) {
12431239 slot_callables = (Callable *)memalloc (sizeof (Callable) * s->slot_map .size ());
12441240 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
12711267
12721268 OBJ_DEBUG_LOCK
12731269
1270+ // If this is a ref-counted object, prevent it from being destroyed during signal
1271+ // emission, which is needed in certain edge cases; e.g., GH-73889 and GH-109471.
1272+ // Moreover, since signals can be emitted from constructors (classic example being
1273+ // notify_property_list_changed), we must be careful not to do the ref init ourselves,
1274+ // which would lead to the object being destroyed at the end of this function.
1275+ bool pending_unref = Object::cast_to<RefCounted>(this ) ? ((RefCounted *)this )->reference () : false ;
1276+
12741277 Error err = OK;
12751278
12761279 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
13201323 memfree (slot_flags);
13211324 }
13221325
1326+ if (pending_unref) {
1327+ // We have to do the same Ref<T> would do. We can't just use Ref<T>
1328+ // because it would do the init ref logic, which is something this function
1329+ // shouldn't do, as explained above.
1330+ if (((RefCounted *)this )->unreference ()) {
1331+ memdelete (this );
1332+ }
1333+ }
1334+
13231335 return err;
13241336}
13251337
0 commit comments