Bump emsdk 4.0.19 -> 5.0.7 (fixes the wasm worker hang) - #6850
Draft
Fedr wants to merge 13 commits into
Draft
Conversation
4.0.19 carries the syscall-proxying race emscripten fixed in #26582 and shipped in 5.0.5: emscripten_proxy_finish signalled the proxy context's condvar after releasing its mutex, so the waiter could return and destroy the context off its own stack before the signal landed. Under -pthread every syscall is proxied to the main thread, so any worker doing file I/O could lose its wakeup and hang. The base stage moves to noble with it - emsdk images are built on noble from the 5.x line on, and binaries linking glibc 2.39 do not run on jammy - which the apt suites follow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
clang-emsdk-6.0.9-pgo is still building in MeshInspector/toolchains, so the download 404s. Comment it out to let this PR's CI exercise the emsdk bump now; restore before merging or the image loses the PGO build-time win. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Its sharedlib/ directory adds example programs that link the .so unconditionally, and on wasm a .so is a side module, so emcc links those executables as a main module where every object has to be PIC. 4.0.19 let it through; 6.0.9's wasm-ld fails them with R_WASM_TABLE_INDEX_SLEB against jpeg_std_error and friends. This script runs only from the emscripten branch of build_thirdparty.sh, so no other platform sees the flag. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
libjpeg-turbo was not the only one: libzip is built shared here and links libmbedcrypto.a, whose objects are not PIC either, so 6.0.9's wasm-ld fails that link too. The thirdparty scripts all inherit MR_CMAKE_OPTIONS, so setting CMAKE_POSITION_INDEPENDENT_CODE once in the emscripten block covers every one of them instead of fixing them one at a time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
6.0.9 is LLVM 24 and was turning into a toolchain migration rather than a bump: PIC across all thirdparty, then emsdk's own non-PIC zlib port, then fmt failing to compile because clang 24 no longer pulls in <cstdlib> transitively. 5.0.5 is where the syscall-proxying fix landed and 5.0.7 is the last of that line, at LLVM 23. The reproducer measured 0 stalls in 24 shards on it, same as 6.0.9. 6.x stays worth doing, separately. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fmt 11.x calls bare malloc/free in format.h and relied on a transitive <cstdlib> that the libc++ in emsdk 5.x no longer provides. It is an unqualified name in a non-dependent template body, so every TU including format.h fails to parse, not just fmt's own os.cc. fmt fixed this properly in 12.0.0 (std::malloc plus the include), but that pin also drags spdlog, which is a decision for another PR. -include cstdlib is two lines, costs nothing, is confined to the emscripten path, and comes out when fmt moves. In build_thirdparty.sh it has to sit after the flag blocks above, which rebuild CXXFLAGS from CFLAGS - and it cannot go in CFLAGS, being C++ only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The CXXFLAGS export did not reach that configure at all - the failing compile line carried only flags set in thirdparty/CMakeLists.txt and not one from the environment. Set it beside the other MR_EMSCRIPTEN flags there instead, which is also where the -w and -pthread ones live. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The file already says it means to use the deprecated API and wraps it in MR_SUPPRESS_WARNING, but the newer libc++ attributes the diagnostic to its own wstring_convert.h rather than to our call, so the pragma never applies and -Werror fails the wasm build. A per-file flag reaches it; emscripten only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t now Every non-PIC link error came from 6.0.9 / LLVM 24; none has appeared on 5.0.7. Meanwhile both apps now fail at wasm-emscripten-finalize with a binaryen parse exception, and feeding PIC thirdparty objects into a module that is not relocatable is the most plausible thing in this branch to produce a binary binaryen cannot read. If the link errors come back, this goes back in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
emscripten attaches findMatchingCatch's dependency on $setTempRet0 only under !DISABLE_EXCEPTION_CATCHING, while the stub that actually calls setTempRet0 is the DISABLE_EXCEPTION_CATCHING one - so with catching off, as we build, nothing emits the symbol and --closure=1 fails with JSC_UNDEFINED_VARIABLE. Worth reporting upstream; until then DEFAULT_LIBRARY_FUNCS_TO_INCLUDE pulls it in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The thirdparty copy is proven - fmt's own os.cc will not compile without it. This one covers MeshLib and MeshInspector sources, which reach format.h through MRPch -> spdlog, and has never been tested on its own. If the app builds go red, it goes straight back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
clang-emsdk-5.0.7-pgo published (clang 23.0.0git, both arches). Restores the toolchain swap this image has always done; the stock ThinLTO-only clang was only ever a stand-in while the toolchain built. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
emscripten's
emscripten_proxy_finishsignalled the proxy context's condition variable afterreleasing its mutex:
In that window the waiting thread takes the mutex, sees
DONE, skipspthread_cond_wait, returnsand destroys the context — which lives on its own stack. The finishing thread then signals a condvar
that is gone, and the thread that should have woken waits forever.
Under
-pthreademscripten proxies every syscall synchronously to the main thread, so anyworker doing file I/O could hit it. That is the wasm STEP-import CI stall, and it explains why the
hang moved between unzip,
std::filesystem::copy,compressZipand the scene load — the stage wasnever the point.
Upstream fix: emscripten-core/emscripten#26582, merged 2026-04-01, shipped in emsdk 5.0.5. We
pin 4.0.19, which predates it.
Measured with a standalone reproducer (two threads doing MEMFS I/O, main thread in a normal event
loop, no MeshLib) at https://github.com/MeshInspector/wasm-memfs-stall — stalls per 480 s shard, 24
shards per cell:
Zero in 144 shards from 5.0.5 up, against roughly one shard in seven below it.
Why 5.0.7 and not 6.0.9
6.0.9 was the first target, and it kept uncovering work rather than being a bump: PIC needed across
all thirdparty, then emsdk's own zlib port is not PIC either and is not ours to rebuild, then fmt
stopped compiling because clang 24 no longer pulls
<cstdlib>in transitively. 5.0.7 is the last ofthe 5.x line, carries the fix, and is LLVM 23 rather than 24. Moving to 6.x is worth doing on its
own schedule.
What changed here
emscripten/emsdk:4.0.19-arm64→5.0.7-arm64, andEMSDK_VERSIONwith it.ubuntu:22.04→ubuntu:24.04, and the apt suitesjammy→noble, for the sameglibc reason.
CMAKE_POSITION_INDEPENDENT_CODE=ONin the emscripten branch ofbuild_thirdparty.sh. Severalthirdparty libs are built shared here and link others statically; a wasm
.sois a side module,so wasm-ld wants every object in it PIC. 4.0.19 tolerated non-PIC archives —
libzip.soagainstlibmbedcrypto.a, and libjpeg-turbo'ssharedlib/examples — and the newer toolchain does not.Every thirdparty script inherits
MR_CMAKE_OPTIONS, so it is set once rather than per library,and only on the emscripten path.
Deliberately not touched
docker/emscripten-generate-c-bindingsDockerfileand the4.0.19-arm64row of.github/workflows/matrix/docker-images-emscripten-c-bindings.jsonstay put. That matrix isintentionally multi-version (it still carries 3.1.38), those images generate bindings rather than
build the shipped wasm, and moving the arm64 row to a noble base additionally needs
VERSION_CODENAMEplumbed through as a build-arg inprepare-images.yml. Happy to fold that in ifyou would rather they move together.
One temporary commit to undo before merge
The PGO toolchain fetch is commented out, so this builds on emsdk's stock clang. Restore it once
MeshInspector/toolchains publishes
clang-emsdk-5.0.7-pgo(building now; emsdk 5.0.7 shipsllvm-project
7b58716d9, clang 23.0.0git).🤖 Generated with Claude Code