Skip to content

Commit 5e4e03f

Browse files
authored
rust: export funcs explicitly invoke static constructors at most once (#533)
* wit-binden-rust: explicitly invoke ctors at start of each export func * rust: wasm_call_ctors only exists in target_arch=wasm32 this is a problem when running `cargo test --workspace` which apparently is building some of this code for native :/ * rust: run ctors at most once * target arch guard
1 parent b8277ba commit 5e4e03f

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

crates/guest-rust/src/lib.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,36 @@ pub use bitflags;
1111

1212
#[doc(hidden)]
1313
pub mod rt {
14+
15+
/// Provide a hook for generated export functions to run static
16+
/// constructors at most once. wit-bindgen-rust generates a call to this
17+
/// function at the start of all component export functions. Importantly,
18+
/// it is not called as part of `cabi_realloc`, which is a *core* export
19+
/// func, but may not execute ctors, because the environment ctor in
20+
/// wasi-libc (before rust 1.69.0) calls an import func, which is not
21+
/// permitted by the Component Model when inside realloc.
22+
///
23+
/// We intend to remove this once rust 1.69.0 stabilizes.
24+
#[cfg(target_arch = "wasm32")]
25+
pub fn run_ctors_once() {
26+
static mut RUN: bool = false;
27+
unsafe {
28+
if !RUN {
29+
// This function is synthesized by `wasm-ld` to run all static
30+
// constructors. wasm-ld will either provide an implementation
31+
// of this symbol, or synthesize a wrapper around each
32+
// exported function to (unconditionally) run ctors. By using
33+
// this function, the linked module is opting into "manually"
34+
// running ctors.
35+
extern "C" {
36+
fn __wasm_call_ctors();
37+
}
38+
__wasm_call_ctors();
39+
RUN = true;
40+
}
41+
}
42+
}
43+
1444
use super::alloc::alloc::Layout;
1545

1646
// Re-export things from liballoc for convenient use.

crates/rust/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,21 @@ impl InterfaceGenerator<'_> {
509509
"
510510
#[allow(unused_imports)]
511511
use wit_bindgen::rt::{{alloc, vec::Vec, string::String}};
512+
513+
// Before executing any other code, use this function to run all static
514+
// constructors, if they have not yet been run. This is a hack required
515+
// to work around wasi-libc ctors calling import functions to initialize
516+
// the environment.
517+
//
518+
// This functionality will be removed once rust 1.69.0 is stable, at which
519+
// point wasi-libc will no longer have this behavior.
520+
//
521+
// See
522+
// https://github.com/bytecodealliance/preview2-prototyping/issues/99
523+
// for more details.
524+
#[cfg(target_arch=\"wasm32\")]
525+
wit_bindgen::rt::run_ctors_once();
526+
512527
"
513528
);
514529

0 commit comments

Comments
 (0)