-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Errors when firing a signal just after awaiting on that signal #89439
Comments
Aren't you doing something "illegal"? You're blocking your
Whatever called the |
It's just a minimal code example to reproduce the bug. The bug is not linked to this happening in |
The direct cause is that extends Node2D
signal my_signal
func _ready():
my_signal.connect(foo, CONNECT_ONE_SHOT)
my_signal.emit()
func foo():
my_signal.emit() Related issue: #28857. How does it affect godot/modules/gdscript/gdscript_vm.cpp Line 2306 in 6128206
godot/modules/gdscript/gdscript_function.cpp Lines 137 to 167 in 6128206
Meaning if the awaited signal is emitted again during such extends Node2D
signal my_signal
func _ready() -> void:
foo()
my_signal.emit() # A
func foo():
await my_signal
my_signal.emit() # B Execution goes something like:
The in godot/modules/gdscript/gdscript_function.cpp Lines 190 to 212 in 6128206
How disconnecting Lines 1121 to 1175 in 6128206
|
@kleonc Thanks for investigating! @AThousandShips it is still a bug, though, right? Why did you remove the |
The infinite recursion should maybe be considered one, but I'd say emitting a signal from the handler for that same signal should be considered recursion and not allowed, I'd say that's expected behavior I'd say the behavior should either be documented, or a blocking check should be added to emitting signals to ensure you don't loop, but allowing this doesn't make sense to me, regardless of one-shot I'd say this is the same limitation as: func foo() -> void:
foo.call_deferred()
func _ready() -> void:
foo.call_deferred() I'm not even sure how this could be "fixed" in any other way than adding a check that errors if you try to emit a signal from within its own handler |
That's what I get for giving a minimal reproducing example :). Consider this: I want to wait for the state to get back to
now in my updating function:
This seems reasonable, right? It gives the above errors. |
What do you mean? As explained above awaiting uses connections, so that's an unfortunate consequence of the same limitation, but I don't think it's solvable to handle this as such, try using deferred calls to update the data perhaps, otherwise I'd say this is a limitation just like call deferred But I'd really say that awaiting something happening and then triggering the same is the same issue and would be error prone |
The problem of giving minimal reproducing example is that it can often be answered by "why would even do that anyway?". I should have given more realistic context from the start. In my opinion, it's not because something is complicated to fix that it's not a bug: I think the above example is a perfectly reasonable usecase for await, and it not working without weird errors being logged constitutes a bug. |
That's not the reason for requesting an MRP, as you can see from the issue template :)
Agreed, I never said it wasn't a bug because of that, please read what I say instead of putting words in my moth, act professionally and please read the code of conduct I'm going to stop engaging with you and I'll wish you a good day To be clear, using func my_func():
foo_1()
foo_2()
await bar
baz_1()
baz_2() Is equivalent to: func my_func():
foo_1()
foo_2()
bar.connect(my_func_2, CONNECT_ONE_SHOT)
func my_func_2():
baz_1()
baz_2() |
@AThousandShips Whether how But regardless of the current The behavior of So:
@BimDav Your original MRP is fine/sufficient on its own, no need for a "real world" example to classify some easily reproducible behavior as a bug / not a bug. |
And I gave my arguments in chat too, and explained here, but I'll restore the label, but I thought this through and presented my arguments, so please take that into account (and don't misrepresent my actions) :) also note that the original labelling of this was made without the knowledge of these details, so it's not irrelevant I'd say the solution should be using something else for await, and enforcing protection against recursion in signals |
Just for information, you can call an async function without waiting for it. So the following example is simpler since it doesn't involve node processing: extends Node
signal my_signal()
func _ready():
async_func()
my_signal.emit()
func async_func():
await my_signal
my_signal.emit() |
This comment was marked as off-topic.
This comment was marked as off-topic.
I'm absolutely against this, there's nothing wrong with the recursive signals on its own. Sure an infinite recursion is unwanted/problematic but if it happens then that would be a user error (assuming no in-engine bugs). Just because recursion can be misued doesn't mean it should be disallowed. BTW it's already allowed hence changing it I'd consider as a breaking change (as I don't think it's a bug / needs a bugfix). And that's also kinda a separate discussion, even possibly a material for a proposal. |
I have a second, similar but different enough case. Here is a sample project:
The issue here seems to be that the receivers list stills contains |
Tested versions
4.2.stable
System information
MacOS, M2
Issue description
Errors are logged when firing a signal just after awaiting on that signal. It seems that the await object is not properly cleaned up and is still partly waiting on the signal.
gives
Steps to reproduce
Run the project below or the code sample above.
Minimal reproduction project (MRP)
await_signal_twice_fired.zip
The text was updated successfully, but these errors were encountered: