GDScript: Fix stack manipulation for await

The stack now contains three special addresses that should no be copied
to the state, since it contains references that creates cycles. They can
be recreated when the function is resumed.

This commit also removes the clearing of stack from the
GDScriptFunctionState destructor, since it should be cleared when the
function exits. The state stack should only be cleared manually if the
instance is freed before the state resumes (which is already being
done). Otherwise this would destruct the stack twice, causing crashes.
This commit is contained in:
George Marques 2022-05-13 14:03:48 -03:00
parent 694baff233
commit 102c312497
No known key found for this signature in database
GPG key ID: 046BD46A3201E43D
2 changed files with 30 additions and 34 deletions

View file

@ -279,7 +279,8 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
void GDScriptFunctionState::_clear_stack() {
if (state.stack_size) {
Variant *stack = (Variant *)state.stack.ptr();
for (int i = 0; i < state.stack_size; i++) {
// The first 3 are special addresses and not copied to the state, so we skip them here.
for (int i = 3; i < state.stack_size; i++) {
stack[i].~Variant();
}
state.stack_size = 0;
@ -300,8 +301,6 @@ GDScriptFunctionState::GDScriptFunctionState() :
}
GDScriptFunctionState::~GDScriptFunctionState() {
_clear_stack();
{
MutexLock lock(GDScriptLanguage::singleton->lock);
scripts_list.remove_from_list();