wasi libc upgrade#5507
Conversation
wasi-libc migrated its build system from a Makefile to CMake between wasi-sdk-16 and wasi-sdk-32, restructuring some source directories and adding new generated headers. Update builder/wasilibc.go to match: - Generate wasi/version.h (previously produced by CMake's configure_file), which defines __wasip1__ and is now widely included and used to gate code. - Follow thread/thrd_sleep.c moving to thread/common/thrd_sleep.c, and add newly-added top-half sources (realpath.c, gethostname.c, inet_addr.c, inet_legacy.c, inet_ntoa.c). - Exclude internal/emulate_wait4.c, a new Linux wait4 emulation file that needs sys/wait.h, which isn't relevant on WASI. - Exclude newly-added wasip2/wasip3-only socket sources that now live alongside the wasip1 sources in libc-bottom-half/sources, and pick up the new libc-bottom-half/sources/math subdirectory. Bump the wasi-libc cache version to invalidate stale build caches. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Wasip2 previously got its libc from a ~1300-line hand-written Go
implementation (src/syscall/libc_wasip2.go) calling wasi:cli/filesystem/io
component bindings directly. wasi-libc upstream already ships a C
implementation of the same wasip2 surface (wasip2.c, wasip2_stdio.c,
descriptor_table.c, socket support), generated from the same WIT
interfaces, so link wasip2 against that instead.
- builder/wasilibc.go: turn libWasiLibc into a newWasiLibc(preview, name)
factory. libWasiLibcWasip2 builds with __wasip2__ defined and the
descriptor-table-based socket/stdio sources instead of wasip1's
cloudlibc syscalls. Distinct library name since the build cache is
keyed by name+triple and both targets share the same wasm32 triple.
- builder/build.go / targets/wasip2.json: route the "wasi-libc" case to
the wasip2 variant when the wasip2 build tag is set.
- src/syscall/syscall_libc.go and syscall_libc_wasi.go were already
shared between wasip1/wasip2 (linker-resolved //export symbols), so
they needed no changes. env_libc.go/errno_wasilibc.go are now shared
too; the wasip2-only mini-libc files are deleted.
- Environ() needed to move to wasip1/wasip2-specific files
(environ_libc.go / environ_wasip2.go): wasi-libc's eager,
constructor-based environ population is fine for wasip1 (a plain core
wasm module) but traps under wasip2's component model when it fires
reentrantly during cabi_realloc ("cannot leave component instance").
wasip2 uses wasi-libc's documented lazy __wasilibc_get_environ()
accessor instead.
- runtime_wasip2.go: cabi_realloc now goes through the malloc-tracked
libc_realloc instead of the GC-internal realloc, since wasi-libc's C
code (e.g. wasip2_string_free) frees buffers allocated during
component-ABI lifting with a plain free().
- lib/wasi-libc-wasip2-stub.c: satisfies wasip2.c's forced-link
reference to wasi-libc's own crt1 component-type metadata, which
TinyGo doesn't build (it provides its own entry points and its own
component-embedding step).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
c38f864 to
36fb419
Compare
lib/wasi-libc-wasip2-stub.c lives outside the wasi-libc submodule (like lib/picolibc-stdio.c) and was missing from the release recipe's copy list, so release builds would fail to build wasip2 binaries. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
| // Use libc_realloc (not the GC-internal realloc) so this allocation is | ||
| // tracked in the same allocs map as malloc/free: wasi-libc's own C code | ||
| // (e.g. wasip2_string_free) takes ownership of buffers allocated here | ||
| // during canonical-ABI lifting and later frees them with a plain free(). | ||
| return libc_realloc(ptr, uintptr(newsize)) |
There was a problem hiding this comment.
If Go types are in the canonical ABI allocated memory, how will these be freed later?
There was a problem hiding this comment.
Hmm.. yeah. This is the one Claude change I wasn't certain about. We already have ownership issues with cabi_realloc. It genuinely pointed out an issue, but I'm not convinced this is the correct fix (as opposed to needing to track these allocations elsewhere.) We need to figure out the best way forward (q.v. #4897 )
There was a problem hiding this comment.
Actually, if the cabi_realloc allocated memory holds pointers to Go types, I'm not concerned about them being free'd later, I'm concerned about them accidently being freed now due to not having any other reference. (I'll need to double check that C buffers end up being ignored as "not in heap")
There was a problem hiding this comment.
It's weird but this might be half of the right fix—don't make these allocations visible or owned by the GC until the types are handed to the Go code.
I have an old (stale) fix PR for this: #4897
Worth another look?
No description provided.