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
Currently WASI program are launched by calling a function named _start. This is the name that C compilers have historically used. It's an option question whether we should just use the wasm start function rather than having an export with a designated name. However, as long as _start is not the wasm start function, it'd be good to use a different name to avoid confusion.
That's a good point, we should consider that option as well.
There is a potential wrinkle, in that a module's exports aren't available to other code while its wasm start function is executing. We'll need to convince ourselves that we'll never have a situation where wasm code calls out into something that then calls one of the wasm code's exports.
Reacted by Sergei Shulepov, Brandon Fish and Joachim Breitner
I can think of a situation where the wasm start function can't be used: a language runtime that JIT compiles a new wasm module and tries to link with itself so the new module can use functions that are built-in to the runtime.
I would agree with @wanderer in that I'd naively expect the native wasm start function to be used for this functionality rather than having a named export. I think @sunfishcode the situation you pointed out is a temporary one, right? I think that's largely an artifact of embedding environments like the web and Node, and with ES module integration for wasm modules I think those points should be fixed?
@programmerjake Regardless of whether we use the wasm start function or an export with a designated name, we can always omit it in modules intended to be used as libraries.
@alexcrichton That's half of it. The other half is the question of whether we'll ever need to support cyclic imports. With cyclic imports, a module could contain a wasm start function which calls an imported function from another module which tries to call one of the first module's exports. Also, with cyclic imports, if we use wasm start functions, it's unclear if we could guarantee that a dynamic library's static constructors are called before a main executable's main function.
@alexcrichton, it goes quite a bit deeper. The start function is meant for initialisation. The current semantics provides strong guarantees about that, namely, that every exported function can safely assume that this initialisation has already been performed when it is called. If we were to break this invariant then that would be a breaking change, because exported functions would now need to defensively check against potentially uninitialised state in order to maintain the module's internal invariants -- it's like being able to invoke a method on an object without the guarantee that its constructor has run.
@rossberg So then the native wasm start function is more like ELF's .init? If so, why is there no corresponding .fini? And why isn't there more than one .init and .fini function possible? That seems like a very short-sighted design.
@npmccallum, I actually have lobbied a bit at times for allowing multiple start functions. :) I don't have a particular opinion about finish functions, since I never had any need for them. But both could be added.
We'll need to convince ourselves that we'll never have a situation where wasm code calls out into something that then calls one of the wasm code's exports.
oh yeah that could be problematic. Especially if someone tries to implement WASI in the browser. In the browser to implement any system call that reads or writes to memory either the module needs to import or export memory. The easiest way is to export the memory. (The other way, importing memory is a bit harder given an arbitrary binary b/c there is no way to know the initial memory size the module expects without doing introspection on the binary (webmassembly.Module.imports doesn't return that info :( ))
@sunfishcode ah that's an excellent point! I'll admit though that I don't really have a good vision of what multi-wasm-modules looks like in WASI. Is the vision that it's similar to dynamic linking in the native world where there's a main executable with a few dynamic libraries automatically loaded? I'd be curious it would be possible to rationalize a multi-wasm-module world with using the start function as well, but it may very well not be possible!
@rossberg ah that's also a good point, but is the invariant that exports can rely on the start function being run true in the hypothetical ES module future? If two wasm modules cyclically import each other one's start must be run first, although I forget if cyclic wasm import changes was forbidden or not. (or the semantics of calling an exported function before start was called if you can get access to it)
I do feel like there's some similarity to the commands/reactors discussion in the sense that a wasi "reactor" I think the start function being thought of as initialization definitely makes sense. In the "command" mode it may not make as much sense to reinterpret start as a main function where, when it exits, the module is destroyed and the process is finished. Perhaps in both cases it makes the most sense to consider the start as an initialization routine and commands just separately execute a well-known named export for the lifetime of the program?
@alexcrichton, ES module integration does not break that property. All cycles conceptually go through JS stubs, and you'd get a JS exception if you tried to invoke a Wasm export too early.
I had previously had the issue with exports being unavailable before start function running which limits what you can do with wasm. I could not setup an exported memory.
I would vote for using a different named function as convention. E.g. _main.
just to make sure this is explicitly stated, it would be impossible to load a wasi module using the wasm js api (or anything that approximates it, like v8's c++ api for wasm) if it used wasm's start directive, because you need to grab the memory export first. wasi_start (and wasi_unstable_start) seem reasonable to me.
@devsnek I don't quite understand this comment. The start function of a wasm module is invoked as part of instantiating a module with its imports; no memory export is required here, since the start function is inside the module itself. This is independent of the embedding.
Thanks for the example, now I see what you are saying. Indeed, if the imported functions (like fd_write) need access exports (like the memory), this will not work from the start function.
Doesn't WASI import its memory so that these cases can work out?
Edit: It seems like WASI would need to import its memory in the WASM start function scenario. This overall case of a memory import and using the WASM start function does seem like it would better support the ES module integration semantics for WASI to run when imported instead of needing a custom call to the _start function.
@Iceber Indeed! For preview1, it no longer makes sense to make breaking changes like renaming _start, and for preview2, the current name for a command entrypoint is run.
Activity
wanderer commentedon Apr 17, 2019
I think the wasm start function is nice since it reuses more of the webassembly spec and keeps WASI a bit more minimal.
sunfishcode commentedon Apr 17, 2019
That's a good point, we should consider that option as well.
There is a potential wrinkle, in that a module's exports aren't available to other code while its wasm start function is executing. We'll need to convince ourselves that we'll never have a situation where wasm code calls out into something that then calls one of the wasm code's exports.
programmerjake commentedon Apr 17, 2019
I can think of a situation where the wasm start function can't be used: a language runtime that JIT compiles a new wasm module and tries to link with itself so the new module can use functions that are built-in to the runtime.
alexcrichton commentedon Apr 17, 2019
I would agree with @wanderer in that I'd naively expect the native wasm
startfunction to be used for this functionality rather than having a named export. I think @sunfishcode the situation you pointed out is a temporary one, right? I think that's largely an artifact of embedding environments like the web and Node, and with ES module integration for wasm modules I think those points should be fixed?sunfishcode commentedon Apr 17, 2019
@programmerjake Regardless of whether we use the wasm start function or an export with a designated name, we can always omit it in modules intended to be used as libraries.
@alexcrichton That's half of it. The other half is the question of whether we'll ever need to support cyclic imports. With cyclic imports, a module could contain a wasm start function which calls an imported function from another module which tries to call one of the first module's exports. Also, with cyclic imports, if we use wasm start functions, it's unclear if we could guarantee that a dynamic library's static constructors are called before a main executable's main function.
npmccallum commentedon Apr 17, 2019
I'm also in favor of the native wasm start function.
rossberg commentedon Apr 17, 2019
@alexcrichton, it goes quite a bit deeper. The start function is meant for initialisation. The current semantics provides strong guarantees about that, namely, that every exported function can safely assume that this initialisation has already been performed when it is called. If we were to break this invariant then that would be a breaking change, because exported functions would now need to defensively check against potentially uninitialised state in order to maintain the module's internal invariants -- it's like being able to invoke a method on an object without the guarantee that its constructor has run.
npmccallum commentedon Apr 17, 2019
@rossberg So then the native wasm start function is more like ELF's
.init? If so, why is there no corresponding.fini? And why isn't there more than one.initand.finifunction possible? That seems like a very short-sighted design.rossberg commentedon Apr 17, 2019
@npmccallum, I actually have lobbied a bit at times for allowing multiple start functions. :) I don't have a particular opinion about finish functions, since I never had any need for them. But both could be added.
npmccallum commentedon Apr 17, 2019
@rossberg So it sounds like we need three things:
.init,.finiand_start.wanderer commentedon Apr 17, 2019
oh yeah that could be problematic. Especially if someone tries to implement WASI in the browser. In the browser to implement any system call that reads or writes to memory either the module needs to import or export memory. The easiest way is to export the memory. (The other way, importing memory is a bit harder given an arbitrary binary b/c there is no way to know the initial memory size the module expects without doing introspection on the binary (webmassembly.Module.imports doesn't return that info :( ))
rossberg commentedon Apr 17, 2019
@wanderer, the latter will of course be rectified by the JS type reflection proposal. ;)
alexcrichton commentedon Apr 17, 2019
@sunfishcode ah that's an excellent point! I'll admit though that I don't really have a good vision of what multi-wasm-modules looks like in WASI. Is the vision that it's similar to dynamic linking in the native world where there's a main executable with a few dynamic libraries automatically loaded? I'd be curious it would be possible to rationalize a multi-wasm-module world with using the
startfunction as well, but it may very well not be possible!@rossberg ah that's also a good point, but is the invariant that exports can rely on the
startfunction being run true in the hypothetical ES module future? If two wasm modules cyclically import each other one's start must be run first, although I forget if cyclic wasm import changes was forbidden or not. (or the semantics of calling an exported function beforestartwas called if you can get access to it)I do feel like there's some similarity to the commands/reactors discussion in the sense that a wasi "reactor" I think the start function being thought of as initialization definitely makes sense. In the "command" mode it may not make as much sense to reinterpret
startas a main function where, when it exits, the module is destroyed and the process is finished. Perhaps in both cases it makes the most sense to consider thestartas an initialization routine and commands just separately execute a well-known named export for the lifetime of the program?rossberg commentedon Apr 17, 2019
@alexcrichton, ES module integration does not break that property. All cycles conceptually go through JS stubs, and you'd get a JS exception if you tried to invoke a Wasm export too early.
bjfish commentedon Apr 17, 2019
I had previously had the issue with exports being unavailable before start function running which limits what you can do with wasm. I could not setup an exported memory.
I would vote for using a different named function as convention. E.g.
_main.3 remaining items
devsnek commentedon Apr 23, 2019
just to make sure this is explicitly stated, it would be impossible to load a wasi module using the wasm js api (or anything that approximates it, like v8's c++ api for wasm) if it used wasm's start directive, because you need to grab the memory export first.
wasi_start(andwasi_unstable_start) seem reasonable to me.titzer commentedon Apr 29, 2019
@devsnek I don't quite understand this comment. The start function of a wasm module is invoked as part of instantiating a module with its imports; no memory export is required here, since the start function is inside the module itself. This is independent of the embedding.
devsnek commentedon Apr 29, 2019
@titzer assuming you run this with something resembling the wasm js api:
titzer commentedon Apr 29, 2019
Thanks for the example, now I see what you are saying. Indeed, if the imported functions (like
fd_write) need access exports (like the memory), this will not work from the start function.guybedford commentedon Apr 29, 2019
Doesn't WASI import its memory so that these cases can work out?
Edit: It seems like WASI would need to import its memory in the WASM start function scenario. This overall case of a memory import and using the WASM start function does seem like it would better support the ES module integration semantics for WASI to run when imported instead of needing a custom call to the _start function.
Add badges to README (WebAssembly#19)
Iceber commentedon Jun 13, 2023
@sunfishcode Hi, We're moving away from preview-1(legacy wasi) and towards component model, do we still need to talk about
_start?sunfishcode commentedon Jun 13, 2023
@Iceber Indeed! For preview1, it no longer makes sense to make breaking changes like renaming
_start, and for preview2, the current name for a command entrypoint isrun.Update to the latest wasi-proposal-repo format. (WebAssembly#19)
Merge pull request WebAssembly#19 from WebAssembly/pch/preopens_are_i…
Remove `allocate`. (WebAssembly#64)
Merge pull request WebAssembly#19 from WebAssembly/add-response-outpa…
Merge pull request WebAssembly#19 from badeend/new-proposal-template