wasmtime: In wasmtime CLI, passing --tcplisten argument breaks --dir

Test Case

testcase.zip

Steps to Reproduce

  1. Extract main.wasm from the test case zip file. Or compile it yourself using WASI SDK and the following source code, e.g. via ~/wasi-sdk/bin/clang main.c --sysroot ~/wasi-sdk/share/wasi-sysroot -o main.wasm if you have WASI SDK at ~/wasi-sdk.
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>

int main (void) {
  DIR *dp = opendir ("./");
  struct dirent *ep;

  if (dp != NULL) {
    while ((ep = readdir (dp)))
      printf("%s\n", ep->d_name);
    closedir(dp);
  }
  else
    printf("Couldn't open the directory\n");

  return 0;
}
  1. Run wasmtime main.wasm --dir=. and observe it print a directory listing
  2. Run wasmtime main.wasm --dir=. --tcplisten=127.0.0.1:9000 and observe it fail to do so (it will print Couldn’t open the directory)

Expected Results

I expect that --tcplisten should not break the directory mapping.

Actual Results

Passing --tcplisten makes it behave as if you didn’t pass --dir=..

Versions and Environment

Wasmtime version or commit: 0.35.1

Operating system: linux

Architecture: x86_64

Extra Info

Other than this, --tcplisten works brilliantly and I’ve been able to implement a nontrivial web server application using this flag and the new sock_accept API.

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 34 (24 by maintainers)

Commits related to this issue

Most upvoted comments

Almost yeah, although the component part doesn’t require any work on Wasmtime’s side, but it may require more work on y’all’s side if you’re not already using components.

I can try to summarize as well a bit if that helps. There’s more-or-less three different ways to go about solving this:

Fix this single issue in isolation

There’s quite a bit of discussion on this thread, and for example I haven’t reviewed the above possible fix mentioned. Fixing this issue in isolation will require confirming that it actually works with wasi-libc which seems like a hazard given the above discussion. I haven’t dug into this myself because sockets in preview1 are not something we’d like to breathe more life into at this time. Instead we’re looking ideally to encourage users to use the preview2 implementation where possible. That being said from a perspective of “I just want something working” this is probably the easiest route since it has nothing to do with components and it’s probably just taking existing stuff and wiring it together a bit differently.

Implement sock_accept in the preview1 adapter.

This effectively boils down to my above thoughts in filling out this function. This requires writing code in the adapter which is not a trivial task. This additionally is something I’d ideally prefer to avoid if we can to again avoid breathing more life into preview1 sockets. Additionally a major snag here is that preview1 has no way to open a socket, meaning that any sockets in use today must have been supplied as a preopen. WASI preview2 has no mechanism, at this time at least, for preopened sockets. It has preopened directories but not preopened sockets. This means that even if the preview1 adapter were filled out it likely wouldn’t work for your use case as-is because you’d still have no means of configuring a preopened socket on the host.

Use components

Using components in their entirety involves directly using the wasi:sockets APIs which gives you access to opening sockets, accepting sockets, etc. This all works as-is today and requires no changes to Wasmtime. Depending on how you’re running components though this may require changes on your end which may be expansive.


If you’d like I can also talk through some of these routes in more detail over video. Otherwise also happy to follow-up here too.

Hi, is there any progress on this issue? I would like to use --tcplisten to experiment with sockets from CPython WASI port. For now Python also requires --mapdir or --dir to mount Python’s stdlib.

Hi, thanks for raising this since I hit the same problem when implementing a web server that serve static files. I am wondering if there is a consensus on how to fix it? Could be the case based on this discussion above but I am not 100% sure.

@bjorn3 said:

According to man sd_listen_fds the first socket must be at fd 3 (so preopened directories must be after the preopened sockets, not before)

Then @haraldh said:

A combination of fd_prestat_get() for the directories and fd_fdstat_get() checking fs_filetype == SocketStream could be used without extending the WASI spec.

So is it correct to assume that it is possible to fix this issue without extending the WASI spec, in a compliant way with man sd_listen_fds (preopened directories must be after the preopened sockets) just by refining how Wasmtime handles this?

Happy to try crafting a PR with proper guidance.