Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename _start #19

Closed
sunfishcode opened this issue Apr 17, 2019 · 25 comments
Closed

Rename _start #19

sunfishcode opened this issue Apr 17, 2019 · 25 comments
Labels
discussion A discussion that doesn't yet have a specific conclusion or actionable proposal.

Comments

@sunfishcode
Copy link
Member

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.

@wanderer
Copy link

I think the wasm start function is nice since it reuses more of the webassembly spec and keeps WASI a bit more minimal.

@sunfishcode
Copy link
Member Author

sunfishcode commented 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
Copy link
Contributor

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
Copy link
Contributor

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?

@sunfishcode
Copy link
Member Author

@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
Copy link
Contributor

I'm also in favor of the native wasm start function.

@rossberg
Copy link
Member

@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
Copy link
Contributor

@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.

@rossberg
Copy link
Member

@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
Copy link
Contributor

@rossberg So it sounds like we need three things: .init, .fini and _start.

@wanderer
Copy link

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 :( ))

@rossberg
Copy link
Member

@wanderer, the latter will of course be rectified by the JS type reflection proposal. ;)

@alexcrichton
Copy link
Contributor

@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?

@rossberg
Copy link
Member

@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
Copy link

bjfish commented 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.

@binji
Copy link
Member

binji commented Apr 17, 2019

I actually have lobbied a bit at times for allowing multiple start functions.

It's unfortunate that we didn't leave ourselves a way to extend this in the binary format. I suppose we'd have to add a new section if we want to provide this in the core wasm spec.

@rossberg
Copy link
Member

@binji, does anything prevent us from allowing multiple start sections?

@binji
Copy link
Member

binji commented Apr 17, 2019

Good point, I guess not. It doesn't really match the rest of the format, but adding a new section is probably worse.

@devsnek
Copy link
Member

devsnek commented 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 (and wasi_unstable_start) seem reasonable to me.

@titzer
Copy link

titzer commented 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
Copy link
Member

devsnek commented Apr 29, 2019

@titzer assuming you run this with something resembling the wasm js api:

(module
  (import "wasi_unstable" "fd_write"
    (func $fd_write (param i32) (param i32) (param i32) (result i32)))

  (memory (export "memory") 1)

  (data (i32.const 16)
    "Hello, World"
  )

  (func $hello
    (i32.store (i32.const 0) (i32.const 12))
    (i32.store (i32.const 4) (i32.const 16))
    ;; implementation of fd_write really needs access to that
    ;; `memory` export right here, but `new WebAssembly.Instance`
    ;; hasn't even returned yet, the export isn't accessable
    (call $fd_write (i32.const 1) (i32.const 0) (i32.const 1))
    (drop)
  )

  (start $hello)

  ;; (export "_start" (func $hello))
)

@titzer
Copy link

titzer commented 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
Copy link
Contributor

guybedford commented 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.

@Iceber
Copy link

Iceber commented 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
Copy link
Member Author

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion A discussion that doesn't yet have a specific conclusion or actionable proposal.
Projects
None yet
Development

No branches or pull requests