-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
Hello, I'm having problems with thread_local variables when the build is performed without -pthread and with -flto enabled.
I've noticed that when the runtime arrives at a thread_local variable, there is a crash. It seems like the variable was declared as a temporal variable (if inside a function scope) instead of a static variable. For global variables, it seems like the initialization value is not guaranteed to be 0.
With -pthread compile and link flag, the problem goes away, but I need a specific build without pthreads to support environments that don't support SharedArrayBuffer due to CORS problems.
The same thing happens if we remove the -flto compile and link flag, but we want to have the smallest possible binary.
As a workaround, I've defined a custom symbol to mark thread_local variables in our code. Something like this:
#if defined(__EMSCRIPTEN_PTHREADS__)
#define au_thread_local thread_local
#else
#define au_thread_local
#endif
But for other third-party libraries, or even Emscripten itself, this is not possible and the workaround is more hacky. In particular, Emscripten uses thread_local variables in <emscripten/val.h> and <emscripten/bind.h> header files. If you try to use coroutines, then you will have a crash inside the <emscripten/val.h> file:
template<EM_METHOD_CALLER_KIND Kind, typename ReturnType, typename... Args>
struct Signature {
/*
typedef typename BindingType<ReturnType>::WireType (*MethodCaller)(
EM_VAL object,
EM_VAL method,
EM_DESTRUCTORS* destructors,
typename BindingType<Args>::WireType...);
*/
static EM_METHOD_CALLER get_method_caller() {
static constexpr WithPolicies<>::ArgTypeList<ReturnType, Args...> args;
thread_local EM_METHOD_CALLER mc = _emval_get_method_caller(args.getCount(), args.getTypes(), Kind);
return mc;
}
};
For this specific case, this is the workaround that is working for me. Instead of including directly the header <emscripten/val.h> I have to include a custom file called "emscriptenVal.h" with the next content:
#if !defined(__CAN_USE_THREADS)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wkeyword-macro"
// In Emscripten if we activate LTO then the NoThreads build fails with thread_local variables treating them as
// local temporal variables, instead of static variables
#define thread_local static
#endif
#include <emscripten/val.h>
#if !defined(__CAN_USE_THREADS)
#undef thread_local
#pragma clang diagnostic pop
#endif
Version of emscripten/emsdk:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.68 (ceee49d)
clang version 20.0.0git (https:/github.com/llvm/llvm-project 5cc64bf60bc04b9315de3c679eb753de4d554a8a)
Target: wasm32-unknown-emscripten
Thread model: posix
Full link command and output with -v appended:
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/upstream/bin\clang.exe" --version
"D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\tools\file_packager.bat" D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.data --from-emcc --embed D:/Code/Nebula/Nebula-Viewer/Code/Src/GoldenViewer/../../../_Output/desktop/chrome.gtpak@/chrome.gtpak D:/Code/Nebula/Nebula-Viewer/Code/Src/GoldenViewer/../../../_Output/scripts/chrome_scripts.gtpak@/chrome_scripts.gtpak --no-node --obj-output=C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\embedded_files.o
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/upstream/bin\wasm-ld.exe" -o D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.wasm -lembind-rtti Src/GoldenViewer/CMakeFiles/GoldenViewer.dir/Distribution/src/GenericEntryPoint.cpp.o Src/GoldenViewerLib/Distribution/libGoldenViewerLib.a Libs/GameEngine/Distribution/libGameEngine.a Libs/Aurora/Code/Libs/bullet/Distribution/libbullet.a clip_external-prefix/src/clip_external-build/Distribution/libclip.a Libs/Aurora/Code/Src/auVideo/Distribution/libauVideo.a Libs/Aurora/Code/Libs/freetype/Distribution/libfreetype.a ktx_read_external-prefix/src/ktx_read_external-build/Distribution/libktx_read.a Libs/Aurora/Code/Libs/imgui/Distribution/libimgui.a Libs/Aurora/Code/Src/auGeom/Distribution/libauGeom.a Libs/Aurora/Code/Src/auImage/Distribution/libauImage.a png_static_external-prefix/src/png_static_external-build/Distribution/libpng16.a webp_external-prefix/src/webp_external-build/Distribution/libwebp.a webp_external-prefix/src/webp_external-build/Distribution/libwebpdecoder.a webp_external-prefix/src/webp_external-build/Distribution/libsharpyuv.a avif_external-prefix/src/avif_external-build/Distribution/libavif.a aom_external-prefix/src/aom_external-build/Distribution/libaom.a yuv_external-prefix/src/yuv_external-build/Distribution/libyuv.a Libs/Aurora/Code/Src/auSound/Distribution/libauSound.a Libs/Aurora/Code/Libs/libvorbis-1.3.7/Distribution/liblibvorbis-1.3.7.a Libs/Aurora/Code/Src/auNetwork/Distribution/libauNetwork.a Libs/Aurora/Code/Src/auCore/Distribution/libauCore.a fmt_external-prefix/src/fmt_external-build/Distribution/libfmt.a zlibstatic_external-prefix/src/zlibstatic_external-build/Distribution/libz.a Libs/Aurora/Code/Libs/yajl/Distribution/libyajl.a Libs/Aurora/Code/Libs/lua/Distribution/liblua_static.a -LD:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\lto -lfetch C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\embedded_files.o D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\lto\libSDL2.a -lGL-webgl2-getprocaddr -lal -lhtml5 -lc_optz -lbulkmemory -lstubs -lc -ldlmalloc -lcompiler_rt -lc++-noexcept -lc++abi-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr C:\Users\yosoy\AppData\Local\Temp\tmpn2i23s1dlibemscripten_js_symbols.so --strip-debug --export=_emscripten_stack_alloc --export=__getTypeName --export=__funcs_on_exit --export=__wasm_call_ctors --export=emscripten_stack_get_current --export=_emscripten_stack_restore --export=malloc --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=main --export-if-defined=__main_argc_argv --export-if-defined=fflush
--export-table -z stack-size=131072 --max-memory=1073741824 --initial-memory=67108864 --no-entry --table-base=1 --global-base=1024
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/upstream/bin\llvm-objcopy.exe" D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.wasm D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.wasm --remove-section=.debug* --remove-section=producers
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/node/20.18.0_64bit/bin/node.exe" D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\src\compiler.mjs C:\Users\yosoy\AppData\Local\Temp\tmp5blpl22o.json
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/node/20.18.0_64bit/bin/node.exe" D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\src\compiler.mjs C:\Users\yosoy\AppData\Local\Temp\tmp9w4a_2d5.json
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/node/20.18.0_64bit/bin/node.exe" C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\tsgen.js
"D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\node_modules.bin\tsc.cmd" --outFile C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\jsdoc.d.ts --declaration --emitDeclarationOnly --allowJs C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\jsdoc.js
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/upstream\bin\wasm-opt" --strip-target-features --post-emscripten -Oz --low-memory-unused --zero-filled-memory --pass-arg=directize-initial-contents-immutable --no-stack-ir D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.wasm -o D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.wasm --mvp-features --enable-threads --enable-bulk-memory --enable-multivalue --enable-mutable-globals --enable-reference-types --enable-sign-ext
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/node/20.18.0_64bit/bin/node.exe" D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\tools\acorn-optimizer.mjs C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\GoldenViewerNoThreads.js AJSDCE --minify-whitespace -o C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\GoldenViewerNoThreads.jso1.js
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/node/20.18.0_64bit/bin/node.exe" D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\tools\acorn-optimizer.mjs C:\Users\yosoy\AppData\Local\Temp\emcc_acorn_info_6m5d1w8o.js emitDCEGraph --no-print
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/upstream\bin\wasm-metadce" --graph-file=C:\Users\yosoy\AppData\Local\Temp\emcc_dce_graph_vod_qa8s.json D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.wasm -o D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.wasm --mvp-features --enable-threads --enable-bulk-memory --enable-multivalue --enable-mutable-globals --enable-reference-types --enable-sign-ext
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/node/20.18.0_64bit/bin/node.exe" D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\tools\acorn-optimizer.mjs C:\Users\yosoy\AppData\Local\Temp\emcc_acorn_info_ilu11rgi.js applyDCEGraphRemovals --minify-whitespace -o C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\GoldenViewerNoThreads.jso2.js
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/node/20.18.0_64bit/bin/node.exe" D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\tools\acorn-optimizer.mjs C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\GoldenViewerNoThreads.jso2.js AJSDCE --minify-whitespace -o C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\GoldenViewerNoThreads.jso3.js
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/upstream\bin\wasm-opt" --minify-imports-and-exports-and-modules --optimize-level=2 --shrink-level=2 --optimize-stack-ir D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.wasm -o D:\Code\Nebula\Nebula-Viewer_Output\html\wasm\GoldenViewerNoThreads.wasm --mvp-features --enable-threads --enable-bulk-memory --enable-multivalue --enable-mutable-globals --enable-reference-types --enable-sign-ext
"D:/Code/Nebula/Nebula-Viewer/Code/Libs/SDKs/emsdk/node/20.18.0_64bit/bin/node.exe" D:\Code\Nebula\Nebula-Viewer\Code\Libs\SDKs\emsdk\upstream\emscripten\tools\acorn-optimizer.mjs C:\Users\yosoy\AppData\Local\Temp\emcc_acorn_info_y_vvsusf.js applyImportAndExportNameChanges --minify-whitespace -o C:\Users\yosoy\AppData\Local\Temp\emscripten_temp_dylnnf24\GoldenViewerNoThreads.jso4.js