You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Rust 1.67.0 stopped initializing the WASI environment for exported functions on target="wasm32-wasi" #107635
Notice that the call to the $__wasm_call_ctors function is missing in the exported test. This means that when entering the Wasm instance through the exported function, it will not have a correctly set up WASI environment and calls to open files or look up environment variables will fail. The _start function in both versions calls $__wasm_call_ctors and works correctly.
I'm not sure what commit broke this. The only PR that is related to this seems to be this one #105405.
I recognize that it worked in wasm32-wasi in earlier versions, however it was by accident. Rust isn't meant to support having programs with a main function which can be entered without calling the main function.
Are you able to switch the crate to a cdylib, by eg. adding this to Cargo.toml, and removing the main function?
[lib]
crate-type = ["cdylib"]
This configuration is not entirely stable yet, but may work as a temporary workaround.
The workaround works, but it has some significant drawbacks for us. We have been relying on this functionality for the last 2 years. Just to give a bit more context about our use case. We expose an API to wasm modules so that they can create new instances from the same module, but use a different entry point. This requires us to allow entering the module without calling main. And this is one of our core features.
The update to 1.67.0 is a breaking change for all our users. Changing to the [lib] approach without main will also require updating all documentation and tutorials. It also significantly reduces the developer experience around our tooling. For example, it would not be possible to just use cargo run with a set runner anymore to start up applications. The setup would need to be much more complicated.
We have a fairly big community around our products. Just our discord consists of 800+ members and Rust is our primary language. So this change has a significant impact on us. The best outcome for us would be to allow the previous behaviour, both main and explicitly exported functions being allowed to be used as entry points into the instance.
Directly reverting the PR in question would cause regressions for other users, including users who specifically need the change to not run the initializers on arbitrary exports, and who requested this change. I'm looking into other ways to fix this.
@alexcrichton had the idea that we could remove all use of __attribute__((constructor)) from wasi-libc and convert the last few eager initializations to lazy initialization. That will require some care to make sure we can initialize preopens at the right time, but I'll look into it.
Reacted by Bernard Kolobara, Ari Seyhun and Marin Koštić
If I understand correctly, WASI programs have to initialize their own environment, rather than the system function definitions being included via some dynamic linker equivalent transcluding libc-or-whatnot? And I would guess the same for other things, instead of simply having certain things happen implicitly due to the operating system's program loader? Interesting. On most systems, somehow bypassing those two components of the system could have equally annoying consequences, it just doesn't happen because it's (mostly) not possible.
I've now submitted #107866 which changes Rust's use of the global environ variable, which requires wasi-libc to eagerly initialize environment variables to use the wasi-libc __wasilibc_get_environ function which allows it to lazily initialize them. This should have the side effect of fixing at least some instances of the regression here, as eager initialization means that initialization is never done if _start isn't called, while lazy initialization allows it to be done on demand when a function calls std::env::vars() or similar.
Reacted by Jubilee, Bernard Kolobara, Hanif Ariffin and Marin Koštić
I recognize that it worked in wasm32-wasi in earlier versions, however it was by accident. Rust isn't meant to support having programs with a main function which can be entered without calling the main function.
Are you able to switch the crate to a cdylib, by eg. adding this to Cargo.toml, and removing the main function?
[lib]
crate-type = ["cdylib"]
This configuration is not entirely stable yet, but may work as a temporary workaround.
Edit: Is there a tool to do this for me? Something like wasm-tools print --export $name to print the body of the exported function called $name. Is there a jq equivalent for WASM yet?
The latest nightly now includes #107866 and lazily initializes environment variables, at least in simple examples, which I hope will fix the immediate bug with environment variables.
For the more general fix, I've now submitted #108097 which switches Rust's cdylib on Wasm to always contain an _initialize function. This is debatable, and my comment here discusses the options.
Activity
workingjubilee commentedon Feb 3, 2023
cc @sunfishcode re: apparent wasm32-wasi functionality regression
sunfishcode commentedon Feb 3, 2023
I recognize that it worked in wasm32-wasi in earlier versions, however it was by accident. Rust isn't meant to support having programs with a
mainfunction which can be entered without calling themainfunction.Are you able to switch the crate to a cdylib, by eg. adding this to Cargo.toml, and removing the
mainfunction?This configuration is not entirely stable yet, but may work as a temporary workaround.
bkolobara commentedon Feb 3, 2023
The workaround works, but it has some significant drawbacks for us. We have been relying on this functionality for the last 2 years. Just to give a bit more context about our use case. We expose an API to wasm modules so that they can create new instances from the same module, but use a different entry point. This requires us to allow entering the module without calling main. And this is one of our core features.
The update to
1.67.0is a breaking change for all our users. Changing to the[lib]approach without main will also require updating all documentation and tutorials. It also significantly reduces the developer experience around our tooling. For example, it would not be possible to just usecargo runwith a setrunneranymore to start up applications. The setup would need to be much more complicated.We have a fairly big community around our products. Just our discord consists of 800+ members and Rust is our primary language. So this change has a significant impact on us. The best outcome for us would be to allow the previous behaviour, both
mainand explicitly exported functions being allowed to be used as entry points into the instance.sunfishcode commentedon Feb 3, 2023
Directly reverting the PR in question would cause regressions for other users, including users who specifically need the change to not run the initializers on arbitrary exports, and who requested this change. I'm looking into other ways to fix this.
@alexcrichton had the idea that we could remove all use of
__attribute__((constructor))from wasi-libc and convert the last few eager initializations to lazy initialization. That will require some care to make sure we can initialize preopens at the right time, but I'll look into it.workingjubilee commentedon Feb 3, 2023
It's worth noting that while WASI is definitely expected to land in some form, it's not a finished, stable part of WebAssembly, because it's big enough as an idea to have its own WASI subproposals.
If I understand correctly, WASI programs have to initialize their own environment, rather than the system function definitions being included via some dynamic linker equivalent transcluding libc-or-whatnot? And I would guess the same for other things, instead of simply having certain things happen implicitly due to the operating system's program loader? Interesting. On most systems, somehow bypassing those two components of the system could have equally annoying consequences, it just doesn't happen because it's (mostly) not possible.
apiraino commentedon Feb 8, 2023
WG-prioritization assigning priority (Zulip discussion).
@rustbot label -I-prioritize +P-medium
Allow wasi-libc to initialize its environment variables lazily.
sunfishcode commentedon Feb 10, 2023
I've now submitted #107866 which changes Rust's use of the global
environvariable, which requires wasi-libc to eagerly initialize environment variables to use the wasi-libc__wasilibc_get_environfunction which allows it to lazily initialize them. This should have the side effect of fixing at least some instances of the regression here, as eager initialization means that initialization is never done if_startisn't called, while lazy initialization allows it to be done on demand when a function callsstd::env::vars()or similar.hbina commentedon Feb 10, 2023
This workaround doesn't seem to work for me. I compiled, linked and initialize a wasm blob here https://github.com/lapce/lapce/blob/master/lapce-proxy/src/plugin/wasi.rs#L360-L520
And it is trying to compile a wasm of this repo https://github.com/hbina/lapce-prettier
And with some grep-foo, I can see that it is trying to initialize the environment variable eagerly?
Compiling as a
main.rs,Where
_startlooks like thisAnd
handle_rpchere goes into the actual function immediately without initializing anything.Compiling as
lib.rswith the suggestion above,Where
handle_rpclooks likeIt doesn't call ctors because....the dtor is just a dummy?
but it doesn't seem to work still.
Edit: Is there a tool to do this for me? Something like
wasm-tools print --export $nameto print the body of the exported function called $name. Is there a jq equivalent for WASM yet?Rollup merge of rust-lang#107866 - sunfishcode:sunfishcode/wasi-lazy-…
workingjubilee commentedon Feb 12, 2023
@hbina Can you try again with the latest nightly? It should be carrying the partial fix mentioned, which should cover your case.
hbina commentedon Feb 12, 2023
Hi @workingjubilee I have updated my previous post to add some clarity and use
+nightlyand it still doesn't work :( Whatever happened to_initialize?sunfishcode commentedon Feb 16, 2023
The latest nightly now includes #107866 and lazily initializes environment variables, at least in simple examples, which I hope will fix the immediate bug with environment variables.
For the more general fix, I've now submitted #108097 which switches Rust's
cdylibon Wasm to always contain an_initializefunction. This is debatable, and my comment here discusses the options.