emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.81k stars 3.31k forks source link

Unexpected behaviour with freopen function when redirecting stdout #19347

Open madmortigan opened 1 year ago

madmortigan commented 1 year ago

Hello

This is a problem with the emscripten compiler for Web Assembly with Nodefs support, from what I can tell.

Unexpected behaviour with freopen function when redirecting stdout

When attempting to use the function freopen to redirect

I have modified the standard Emscripten test “emsdk\upstream\emscripten\test\fs\test_nodefs_rw.c” to test this.

I have tested this with various versions of emsdk, using the build and test lines:

cmcc test_nodefs_reopen.c -lnodefs node a.out.js redirect stdout to stdout.txt

With the expected output above, but additionally there should be a file stdout.txt that contains the line

“test message to stdout using printf”. test_nodefs_reopen.c.txt test_nodefs_reopen.c.txt

However, I find that this is empty with emsdk versions 3.1.9 and higher. With emsdk versions 3.1.8 and lower (to 1.39.4, the earliest I have tested) the stdout.txt file does contain the printf output.

I am using Windows to build and run, but I have also had it tested on Linux with 3.1.9 (fails) and 1.39.6 (works ok).

We have also seen the stdout apparently redirected to another opened file, not the expected one, but that isn’t something I can clearly reproduce.

Version of emscripten/emsdk:

Please include the output emcc -v here

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.38 (9eff02bc816c50ab0e3b70a3bd5b72a8dc2893a2)

clang version 17.0.0 (https://github.com/llvm/llvm-project 004bf170c6cbaa049601bcf92f86a9459aec2dc2)

Target: wasm32-unknown-emscripten

Thread model: posix

InstalledDir: C:\apps\Webassembly\emsdk_3.1.38\upstream\bin

Failing command line in full:

If this is compile or link-time failure please include the full failing command

along with its entire output.

Full link command and output with -v appended:

Even for runtime issues it helps a lot if you can include the full link command.

Adding -v to the link command will show all of the sub-commands run which

can help us diagnose your issue.

c:\workdir\emtest>emcc -v test_nodefs_reopen.c -lnodefs.js

"C:/apps/Webassembly/emsdk_3.1.38/upstream/bin\clang.exe" --version

"C:/apps/Webassembly/emsdk_3.1.38/upstream/bin\clang.exe" -target wasm32-unknown-emscripten -fignore-exceptions -fvisibility=default -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -DEMSCRIPTEN -Werror=implicit-function-declaration --sysroot=C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\sysroot -Xclang -iwithsysroot/include\fakesdl -Xclang -iwithsysroot/include\compat -v test_nodefs_reopen.c -c -o C:\Users\bradley\AppData\Local\Temp\emscripten_temp_18egp8ya\test_nodefs_reopen_0.o

clang version 17.0.0 (https://github.com/llvm/llvm-project 004bf170c6cbaa049601bcf92f86a9459aec2dc2)

Target: wasm32-unknown-emscripten

Thread model: posix

InstalledDir: C:\apps\Webassembly\emsdk_3.1.38\upstream\bin

(in-process)

"C:\apps\Webassembly\emsdk_3.1.38\upstream\bin\clang.exe" -cc1 -triple wasm32-unknown-emscripten -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_nodefs_reopen.c -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-cpu generic -debugger-tuning=gdb -v "-fcoverage-compilation-dir=c:\workdir\emtest" -resource-dir "C:\apps\Webassembly\emsdk_3.1.38\upstream\lib\clang\17" -D EMSCRIPTEN -isysroot "C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\sysroot" -internal-isystem "C:\apps\Webassembly\emsdk_3.1.38\upstream\lib\clang\17\include" -internal-isystem "C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\sysroot/include/wasm32-emscripten" -internal-isystem "C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\sysroot/include" -Werror=implicit-function-declaration "-fdebug-compilation-dir=c:\workdir\emtest" -ferror-limit 19 -fmessage-length=192 -fvisibility=default -fgnuc-version=4.2.1 -fignore-exceptions -fcolor-diagnostics "-iwithsysroot/include\fakesdl" "-iwithsysroot/include\compat" -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -o "C:\Users\bradley\AppData\Local\Temp\emscripten_temp_18egp8ya\test_nodefs_reopen_0.o" -x c test_nodefs_reopen.c

clang -cc1 version 17.0.0 based upon LLVM 17.0.0git default target x86_64-pc-windows-msvc

ignoring nonexistent directory "C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\sysroot/include/wasm32-emscripten"

include "..." search starts here:

include <...> search starts here:

C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\sysroot/include\fakesdl

C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\sysroot/include\compat

C:\apps\Webassembly\emsdk_3.1.38\upstream\lib\clang\17\include

C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\sysroot/include

End of search list.

cache:INFO: generating system asset: symbol_lists/bcfe2563b795e974ea32f1e7e59d622e22ac273b.json... (this will be cached in "C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\symbol_lists\bcfe2563b795e974ea32f1e7e59d622e22ac273b.json" for subsequent builds)

"C:/apps/Webassembly/emsdk_3.1.38/node/15.14.0_64bit/bin/node.exe" C:\apps\Webassembly\emsdk3.1.38\upstream\emscripten\src\compiler.js C:\Users\bradley\AppData\Local\Temp\tmp06mgpjs.json --symbols-only

cache:INFO: - ok

"C:/apps/Webassembly/emsdk_3.1.38/upstream/bin\wasm-ld.exe" -o a.out.wasm C:\Users\bradley\AppData\Local\Temp\emscripten_temp_18egp8ya\test_nodefs_reopen_0.o -LC:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten -lGL -lal -lhtml5 -lstubs-debug -lnoexit -lc-debug -ldlmalloc -lcompiler_rt -lc++-noexcept -lc++abi-debug-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr C:\Users\bradley\AppData\Local\Temp\tmpoauvtvi7libemscripten_js_symbols.so --strip-debug --export-if-defined=main --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_argc_argv --export-if-defined=fflush --export=emscripten_stack_get_end --export=emscripten_stack_get_free --export=emscripten_stack_get_base --export=emscripten_stack_get_current --export=emscripten_stack_init --export=stackSave --export=stackRestore --export=stackAlloc --export=__errno_location --export=get_temp_ret --export=set_temp_ret --export=__wasm_call_ctors --export-table -z stack-size=65536 --initial-memory=16777216 --no-entry --max-memory=16777216 --stack-first

"C:/apps/Webassembly/emsdk_3.1.38/upstream\bin\wasm-emscripten-finalize" --dyncalls-i64 --pass-arg=legalize-js-interface-exported-helpers a.out.wasm -o a.out.wasm --detect-features

"C:/apps/Webassembly/emsdk_3.1.38/node/15.14.0_64bit/bin/node.exe" C:\apps\Webassembly\emsdk_3.1.38\upstream\emscripten\src\compiler.js C:\Users\bradley\AppData\Local\Temp\tmpk5ia88of.json

"C:/apps/Webassembly/emsdk_3.1.38/upstream/bin\llvm-objcopy.exe" a.out.wasm a.out.wasm --remove-section=.debug* --remove-section=producers

sbc100 commented 1 year ago

I would not be surprised to learn that there is bug here when using freopen to redirect stdout. Can I ask why you are trying to do this? Is it important for your app for a some reason?

Are you away that we have a mechanism for capturing stdout that you can use from JS: You can do Module['print'] = .... Would that be enough for your use case?

In the mean time if you have a patch that fixes the freopen issue that would be most welcome.

madmortigan commented 1 year ago

Thank you for the response.

It's part of how our legacy testing tool delivers output. It's not part of a production application, but allows us to test our Web Assembly builds on desktop/server using nodefs as part of CI. We could work around this by changing the test program code or probably by changing the tooling (there are some platforms we test on where we don't redirect stdout/stderr). 

We can't realistically use JS, because we don't currently write custom JS.

Unfortunately I don't have a fix for the freopen issue at this stage.

Many thanks

sbc100 commented 1 year ago

Does using -sNODERAWFS make any difference?

madmortigan commented 1 year ago

Thank you for the suggestion. Yes it does make a difference. Using -sNODERAWFS is a viable workaround for me, at least on Windows. I don't know if that indicates I'm doing something wrong with the old method, but I can change to NODERAWFS.