Skip to content

Commit a258465

Browse files
committed
Fix regression in mechanism to hold objects while emitting
1 parent 8ebf8ae commit a258465

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

core/object/object.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)