Skip to content

Fix fdatasync link error with -sWASMFS -flto=thin - #28201

Open
aaalloc wants to merge 1 commit into
emscripten-core:mainfrom
aaalloc:fix_lto_fsync_fdatasync
Open

aaalloc wants to merge 1 commit into
emscripten-core:mainfrom
aaalloc:fix_lto_fsync_fdatasync

Conversation

@aaalloc

@aaalloc aaalloc commented Nov 7, 2026

Copy link
Copy Markdown

From #27939

while compiling

#include <unistd.h>

int main(int argc, char **argv) {
  fsync(0);
  fdatasync(0);
  return 0;
}

You get

wasm-ld: error: import module mismatch for symbol: __wasi_fd_sync
>>> defined as env in /home/paradust/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/thinlto/libwasmfs-debug.a(syscalls.o)
>>> defined as wasi_snapshot_preview1 in /home/paradust/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/thinlto/minimal.wasm.lto.libc-debug.a(fsync.o at 2366516).o
emcc: error: '/home/paradust/emsdk/upstream/bin/wasm-ld -o minimal.wasm /tmp/tmp_mszapyplibemscripten_js_symbols.so -Bstatic --strip-debug -u__cxa_atexit --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=wasmfs_flush --export=_emscripten_stack_alloc --export=setThrew --export=__wasm_call_ctors --export=_emscripten_stack_restore --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=65536 --no-growable-memory --initial-heap=16777216 --no-entry --stack-first --table-base=1 /tmp/emscripten_temp_8xy2kcjf/minimal.o -L/home/paradust/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/thinlto -L/home/paradust/emsdk/upstream/emscripten/src/lib -lGL-getprocaddr -lal -lhtml5 -lstubs-debug -lnoexit -lc-debug -ldlmalloc-debug -lclang_rt.builtins -lc++-debug-noexcept -lc++abi-debug-noexcept -lsockets -lwasmfs_no_fs -lwasmfs-debug -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr' failed (returned 1)

and thats because of this

>>> defined as env in /home/paradust/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/thinlto/libwasmfs-debug.a(syscalls.o)
>>> defined as wasi_snapshot_preview1 in /home/paradust/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/thinlto/minimal.wasm.lto.libc-debug.a(fsync.o at 2366516).o

It seems that fdatasync

int fdatasync(int fd)
{
     return syscall_cp(SYS_fdatasync, fd);
}
// system/lib/libc/musl/arch/emscripten/bits/syscall.h
#define SYS_fdatasync		__syscall_fdatasync


// system/lib/wasmfs/syscalls.cpp
int __syscall_fdatasync(int fd) {
  // TODO: Optimize this to avoid unnecessarily flushing unnecessary metadata.
  // Translate from WASI positive error codes to negative error codes.
  return -__wasi_fd_sync(fd);
}

is practically the same as fsync

int fsync(int fd)
{
#if __EMSCRIPTEN__
	return __wasi_syscall_ret(__wasi_fd_sync(fd));
#else
	return syscall_cp(SYS_fsync, fd);
#endif
}

but here we don't have SYS_fsync definition in system/lib/libc/musl/arch/emscripten/bits/syscall.h, so i assume it never goes into the else, and there you go you have your double definition

I followed how fsync is defined but maybe we can go the other way around by applying how fdatasync was to fsync, i don't know.

I have runned test with

test/runner.py 'other.test_unistd_fdatasync' \
               'other.test_fsync*' \
               'core0.test_unistd_misc*' \
               'lto0.test_unistd_misc*' \
               'lto2.test_unistd_misc*'

and everything pass

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an Emscripten-specific implementation for fdatasync using WASI's __wasi_fd_sync. The reviewer correctly pointed out a bug where a negative error code is passed to __wasi_syscall_ret, which expects a positive error code. This would result in errno being set to a negative value, violating POSIX standards. A code suggestion was provided to remove the minus sign.

Call __wasi_fd_sync directly, like fsync already does, instead of going
through __syscall_fdatasync.
@aaalloc
aaalloc force-pushed the fix_lto_fsync_fdatasync branch from f9ce617 to 6b99fb6 Compare November 7, 2026 00:23
@sbc100

sbc100 commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

I feel like this error not correct and there is probably a fix on the llvm side that fixes the root cause here.. I'm looking into it now.

@sbc100

sbc100 commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

I have a fix on the llvm side: llvm/llvm-project#239883

I'm still not if this is quite the right place to fix the issue..

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.

2 participants