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

Add the ability to call specific modules in wasmtime. #102

Merged
merged 1 commit into from
Apr 22, 2023

Conversation

brendandburns
Copy link

This enables someone to pass /main.wasm#foo as the arg[0] and for it to call a specific method in that WASM file instead of assuming that _start is the only entrypoint.

Copy link
Member

@Mossaka Mossaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the PR! @brendanburns

We are currently holding off merging in new prs until #78 closes.

@brendandburns brendandburns changed the title Add the ability to call specific modules Add the ability to call specific modules in wasmtime. Apr 4, 2023
Copy link
Member

@Mossaka Mossaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@cpuguy83 cpuguy83 merged commit 0288f5f into containerd:main Apr 22, 2023
@codefromthecrypt
Copy link

If I understand correctly, this (e.g. /main.wasm#foo or maybe really main.wasm#foo) would end up being indicated as ENTRYPOINT in the Dockerfile.

Is this pattern done anywhere else? I suppose I want to know how someone would know to ignore a # as a valid file character. My guess is what will happen after this change, for runtimes that aren't aware of this PR, is that they will fail on file-not-found..

Basically, the runtime will think the entry point wasm is literally main.wasm#foo which is a bad experience. Since this project works with multiple runtimes, the user might not know that this special filename encoding is wasmtime specific.

@giuseppe do you know anywhere else that has special logic like this in treatment of the ENTRYPOINT binary?

p.s. even if you can call "foo", you may also need to initialize the wasm, especially as this project is called runwasi. For example, if you try to call an exported function from tinygo compiled to wasi, it will fail if initialization isn't called first (_start), so basically this seems like a hook that is more about wasm than wasi.

@jerbob92
Copy link

jerbob92 commented Apr 27, 2023

I wanted to make you aware of the fact that you can't just call a specific method. See these docs.

If your application is a command module, then it has a _start function, the initialization of the application is compiled into that _start, so you will first have to call _start before calling anything else.

If your application is a reactor module, you will have a _initialize function that you should call before anything else.

For example Emscripten uses the _start/_initialize to initialize the following:

  • The memory allocator
  • Environment variables (__wasi_environ_sizes_get/__wasi_environ_get)
  • The threading system
  • Filesystem preopens (__wasi_fd_prestat_get/__wasi_fd_prestat_dir_name)

Wasi-libc uses the _start/_initialize to initialize the following:

  • The memory allocator
  • The start of runtime (__wasi_clock_time_get) for the clock
  • Environment variables (__wasi_environ_sizes_get/__wasi_environ_get)
  • Filesystem preopens (__wasi_fd_prestat_get/__wasi_fd_prestat_dir_name)
  • The SSP

You can look for __attribute__((constructor({priority}))) to find methods that are compiled into _start/_initialize.

I don't know about other compilers but they probably use a similar system.

@brendandburns
Copy link
Author

Thanks for the feedback! Two replies:

The hash syntax is stolen from Java, eg https://stackoverflow.com/questions/11247793/why-do-some-folks-use-classmethod-instead-of-class-method-in-correspondence

But I think :: is equally valid and we could switch to that.

I tested this with wasmtime + c and it works correctly in the sense that the method executes and returns, a similar call pattern is used in the wasmtime binary if you specify a specific method to call on the command line.

I think what the 'correct' behavior here is is under specified. I was viewing it like a stateless function, in which case that initialization may not make sense, but I agree that things like missing environment variables may confuse the user.

I'll look into adding more clarity and reducing confusion. Thanks again for the feedback!

@codefromthecrypt
Copy link

The hash syntax is stolen from Java, eg https://stackoverflow.com/questions/11247793/why-do-some-folks-use-classmethod-instead-of-class-method-in-correspondence

But I think :: is equally valid and we could switch to that.

I think my point is that any filename encoding will break the ability to know if a binary exists or not, unless all runtimes are taught the special delimiter that might be inside ENTRYPOINT[0]

So, lifecycle concerns aside, this will make format very coupled to one runtime and different than normal docker, too. Is there another way to pass this extra method info in a way your runtime can see it? Also, since this isn't about WASI is there a strong need to support this? I mean was a user asking to do this? It seems for a wasi project, maybe you don't need to scope in something like this because it causes problems with what ENTRYPOINT means (specifically position zero is the real file)

@brendandburns
Copy link
Author

I'm not sure why any other runtime needs to be taught about this. This is intended to be specific to the runwasi

Is entrypoint formally defined anywhere? The best I can see in the spec is:

https://github.com/opencontainers/image-spec/blob/main/config.md

Where it says

Entrypoint: array of strings, OPTIONAL

A list of arguments to use as the command to execute when the container starts. These values act as defaults and may be replaced by an entrypoint specified when creating a container.

Which seems to indicate that it is up to each runtime to interpret what Entrypoint means.

@codefromthecrypt
Copy link

IF this is indeed specific to runwasi then it should be documented somewhere as this is different than OCI runtimes for wasi which will interpret ENTRYPOINT[0] as the binary. It should also implement for all its implementing runtimes, at least to give a proper error. Right now, the only thing that parses this is wasmtime, so if you passed this info to wasmedge I'm pretty sure you'd get an ugly error.

Make sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants