Skip to content

Conversation

@bruvzg
Copy link
Member

@bruvzg bruvzg commented Jan 24, 2026

Fixes #115311

Instead of using arbitrary 2K limit, which is only valid for main thread on release builds, use real stack limits for the check.

Depending on platform and build config, real call depth limits varies from ~100 to 7000.

Tested on macOS, Windows and Linux.

@bruvzg bruvzg added this to the 4.x milestone Jan 24, 2026
@bruvzg bruvzg force-pushed the stack_check branch 4 times, most recently from 5f760a2 to 73eca08 Compare January 24, 2026 21:01
@bruvzg bruvzg marked this pull request as ready for review January 26, 2026 07:09
@bruvzg bruvzg requested review from a team as code owners January 26, 2026 07:09
@lawnjelly
Copy link
Member

If the stack size is platform dependent, is there a danger that we are introducing something that could result in exports failing on some platforms but not others?

@bruvzg
Copy link
Member Author

bruvzg commented Jan 26, 2026

If the stack size is platform dependent, is there a danger that we are introducing something that could result in exports failing on some platforms but not others?

I do not think it will introduce any new potential issues, previously it would crash on overflow, now script will fail with error.
But the stack size is already an inconsistency, so we probably should do something to decreases stack usage (especially in debug builds).

Adjusting stack size for the threads will require to make platform specific Thread implementation for Windows, like we do for macOS, since std::thread cant do it. But it might create new issues with thread local variables (it was an issue in the past, but not the case for macOS, since both use pthread under the hood).

@akien-mga
Copy link
Member

akien-mga commented Jan 26, 2026

I'm wondering if we should hardcode instead the min stack size from all our supported platforms. Using platform-specific limits sounds like it could lead in situations where a script works fine on Linux, but fails on Windows or macOS. In such case it would be better IMO to enforce a lower limit on Linux to take into account cross-platform constraints (most Godot projects are intended to be cross-platform).

@bruvzg
Copy link
Member Author

bruvzg commented Jan 26, 2026

It's not mutually exclusive, adjusting stack size on all platforms makes sense, but it's non-trivial to determine what size we need for each build config, so runtime check should still be safer. And, as I already mention, custom Thread implementation for Windows likely will cause issues with thread local variables on MinGW.

@akien-mga
Copy link
Member

Yeah it makes sense to add a way to retrieve the real stack size for sure.

I wasn't advocating for a custom Thread implementation, but more a GDScript only limit like:

// Low limit to try to take into account the various stack limits on different platforms/build configs.
static constexpr int MAX_CALL_DEPTH = 256;

But I haven't looked into this much so maybe this wouldn't be sufficient or would be too limiting.

@bruvzg
Copy link
Member Author

bruvzg commented Jan 26, 2026

In some debug build configs, the real limit is around 100, which is likely too limiting (this is not accounting for all possible sanitizer builds, which might have even lower limit).

So making the limit higher (either with custom Thread implementation and bigger stack or by decreasing stack usage) is probably the next logical step.

err_func = p_instance->script->local_name.operator String() + "." + err_func;

++call_depth;
#if defined(SANITIZERS_ENABLED)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#if defined(SANITIZERS_ENABLED)
#ifdef SANITIZERS_ENABLED

bool has_overflow = false;
if (Thread::get_stack_limits(&bottom, &top, &frame)) {
uint64_t alloc_size = sizeof(Variant *) * FIXED_ADDRESSES_MAX + sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size;
#if defined(SANITIZERS_ENABLED)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#if defined(SANITIZERS_ENABLED)
#ifdef SANITIZERS_ENABLED

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Debugger does not catch infinite recursion stack overflow on separate thread, instead game just exits with no errors

5 participants