-
-
Notifications
You must be signed in to change notification settings - Fork 21.5k
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
Fix dangling Variants (3.2) #38119
Fix dangling Variants (3.2) #38119
Conversation
Needed for the next commit. That's the only place in all the Godot code base where that's attempted and it's not needed because Objects are not meant to be copied that way.
e22da10
to
31d9d24
Compare
This commit addresses multiple issues with `Variant`s that point to an `Object` which is later released, when it's tried to be accessed again. Formerly, **while running on the debugger the system would check if the instance id was still valid** to print warnings or return special values. Some cases weren't being warned about whatsoever. Also, a newly allocated `Object` could happen to be allocated at the same memory address of an old one, making cases of use hard to find and having **`Variant`s pointing to the old one magically reassigned to the new**. This commit makes the engine realize all these situations **under debugging** so you can detect and fix them. Running without a debugger attached will still behave as it always did. Also the warning messages have been extended and made clearer. All that said, in the name of performance there's still one possible case of undefined behavior: in multithreaded scripts there would be a race condition between a thread freeing an `Object` and another one trying to operate on it. The latter may not realize the `Object` has been freed soon enough. But that's a case of bad scripting that was never supported anyway.
31d9d24
to
d904d05
Compare
Thanks! |
@godotengine/bugsquad This likely fixes many open issues about Variant references being wrongly reassigned to a random node after free. Feel free to hunt them down and close them as fix (another fix for that issue was already merged in |
That's great! Thanks for fixing this critical issue. What's the plan for release builds in 3.x ? Currently we're bound to debug builds since our release builds crash systematically. I couldn't find the mentioned new proposal for that, so could you please provide the link if it exists? Thanks! |
I haven't had time yet, but I'll give it a higher priority in my backlog. |
As far as I can tell, there's not much we can do as users in GDscript to avoid the issue, or is there? We don't use threads, but we do use audio which is multi-threaded under the hood. Unfortunately release builds currently seem to be trading safety for speed which is unfortunate and prohibitive. Since safety prevails, we're stuck to debug builds with the assumed cost of lower fps. |
This commit addresses multiple issues with
Variant
s that point to anObject
which is later released, when it's tried to be accessed again.Formerly, while running on the debugger the system would check if the instance id was still valid to print warnings or return special values. Some cases weren't being warned about whatsoever. Moreover, on release builds you would experiment undefined behavior; specially, crashes.
Also, a newly allocated
Object
could happen to be allocated at the same memory address of an old one, making cases of use hard to find and havingVariant
s pointing to the old one magically reassigned to the new.This commit fixes all these problems:
- On release builds, the instance id check is not performed, so no warnings are printed, but now the validity of theVariant
is checked by more optimal means, allowing the system to act in a controlled manner in those cases, as if it wasnull
, with no crashes, etc.UPDATE: This PR has been updated to remove the checks from release builds. A separate proposal about how to include them for those needing maximum safety will be written, so don't worry. What is done in this PR is already good stuff.
All that said, in the name of performance there's still one possible case of undefined behavior: in multithreaded scripts there would be a race condition between a thread freeing an
Object
and another one trying to operate on it. The latter may not realize theObject
has been freed soon enough. But that's a case of bad scripting that was never supported anyway.Part of the credit for this goes to @reduz, since this is the result of implementing an approach he suggested to me with some additional ideas of mine.
This code is generously donated by IMVU.