Skip to content

Set worker thread stack size to match the main thread - #9158

Open
guybedford wants to merge 1 commit into
WebAssembly:mainfrom
guybedford:thread-stack-size
Open

guybedford wants to merge 1 commit into
WebAssembly:mainfrom
guybedford:thread-stack-size

Conversation

@guybedford

Copy link
Copy Markdown

This fixes a SIGBUS in wasm-opt on macOS when optimizing large modules with deeply recursive passes in parallel.

I've directly verified that this fix fixes a SIGBUS on a large (35MiB) binary on MacOS that I was hitting this issue on.

std::thread uses the platform default stack size for new threads. On macOS that is a fixed 512KB for secondary threads regardless of ulimit -s, so at -O2/-Os on large functions the ThreadPool workers overflow their stack. The same module and flags pass on Linux, where glibc sizes new threads from RLIMIT_STACK, and on Windows, where the linker /STACK reserve already applies to all threads. BINARYEN_CORES=1 also passes since the work then runs on the main thread.

  • On POSIX (non-Windows, non-Emscripten), Thread now creates workers with pthread_create and an explicit stack size via pthread_attr_setstacksize.
  • getWorkerThreadStackSize() uses the RLIMIT_STACK soft limit, falling back to 8MB when unlimited, so workers can recurse as deeply as the main thread and ulimit -s applies to them too. This matches the existing glibc behavior, so Linux is unchanged.
  • Windows and Emscripten builds keep using std::thread.

Test coverage: a new ThreadsTest.WorkerStackSize gtest runs work on every pool thread and asserts the actual worker stack size is at least the requested size. It passes on Linux today and would fail on macOS without this change (verified by forcing a 512KB worker stack locally, which fails with 524288 vs 8388608).

Made with AI assistance under my review

std::thread uses the platform default stack size for new threads, which on
macOS is only 512KB for secondary threads regardless of ulimit -s. Deeply
recursive passes on large functions therefore overflow in ThreadPool workers
and crash with SIGBUS on macOS, while passing on Linux (where glibc sizes
new threads from RLIMIT_STACK) and Windows (where the linker /STACK applies
to all threads).

On POSIX, create workers with pthread_create and an explicit stack size taken
from the RLIMIT_STACK soft limit (8MB if unlimited), so workers can recurse as
deeply as the main thread and ulimit -s applies to them too.
@guybedford
guybedford requested a review from a team as a code owner September 26, 2026 00:41
@guybedford
guybedford requested review from tlively and removed request for a team September 26, 2026 00:41

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant