Stream: git-wasmtime

Topic: wasmtime / Issue #2373 Can't access stdin from a WASI pro...


view this post on Zulip Wasmtime GitHub notifications bot (Nov 06 2020 at 18:42):

flavio edited Issue #2373:

I hope I'm opening this bug on the right GitHub repo, if not please forgive me :sweat_smile:

I've written a simple "echo" program using AssemblyScript and as-wasi. The program reads the user input from STDIN and writes it back to STDOUT.

Unfortunately it looks like I can never get back the input I enter.

This the source code of the AssemblyScript program I'm running:

import "wasi"

import {Console} from "as-wasi"

Console.log("type something");

let input: string | null;
let msg : string = "nothing";

input = Console.readAll();
if (input != null) {
  msg = input!
}

Console.log('I got: ' + msg);

The program can be compiled to a WASM binary by doing:

$ asc echo.ts -b echo.wasm

And it can be run in this way:

$ wasmtime run echo.wasm

The program will start and I'll be able to enter my text. The program will keep reading from STDIN until I send the EOF symbol (I'm on Linux -> CTRL-D).

Unfortunately the input variable is always null.

I would expect the WASM program to be able to read data from stdin. The input object should hold the text I entered on my terminal.

This is my stack:

* wasmtime: 0.21.0
* AssemblyScript: 0.17.1
* as-wasi: 0.4.0

I'm running on a x86_64 Linux box that has openSUSE Tumbleweed

More information...

The as-wasi handles STDIN/STDOUT/STDERR by using instances of the Descriptor class. The library simply opens the file descriptor 0 for STDIN, 1 for STDOUT and 2 for STDERR. In my tests it looks like opening the file descriptor 0 always returns a null instance of Descriptor; this doesn't happen with STDOUT and STDERR.

The same issue happens also when running the program through a custom made Go program I wrote leveraging wasmtime-go.
In that case I even tried to start the WASM binary not by inheriting the parent STDIN, but instead by using a text file I previously created. Also in this case the WASM binary got a null object when reading from the STDIN.

Relevant: a similar WASM binary, generated by translating Rust -> WASM, just works as expected.

Thanks for any kind of help you can give me. I gotta say, WebAssembly and wasmtime are really cool :)

view this post on Zulip Wasmtime GitHub notifications bot (Nov 06 2020 at 19:32):

alexcrichton commented on Issue #2373:

Thanks for the report! This seems like it may be an issue with the wasi support in AssemblyScript possibly, so I'm gonna loop in @torch2424 to see if they can help (or help point you in the right direction)

view this post on Zulip Wasmtime GitHub notifications bot (Nov 06 2020 at 19:43):

peterhuene commented on Issue #2373:

Could it be this line that returns null when bytes read = 0?

view this post on Zulip Wasmtime GitHub notifications bot (Nov 06 2020 at 21:29):

torch2424 commented on Issue #2373:

Thanks for looping me in @alexcrichton :smile:

And yes, @peterhuene , I bet it's falling through to the bottom to return 0 :smile:


@flavio I was able to reproduce this, and what caught my interest was:

The as-wasi handles STDIN/STDOUT/STDERR by using instances of the Descriptor class. The library simply opens the file descriptor 0 for STDIN, 1 for STDOUT and 2 for STDERR. In my tests it looks like opening the file descriptor 0 always returns a null instance of Descriptor; this doesn't happen with STDOUT and STDERR.

So! Yes, in most instances, I've personally noticed stdin was represent by 0. Or perhaps it does on Mac?

But! If you can't get a file descriptor for stdin at 0, then yes it could totally be the cause of this bug.

cc @jedisct1 , as they are the author of as-wasi, and they may have a better hunch than me :smile:

view this post on Zulip Wasmtime GitHub notifications bot (Nov 06 2020 at 23:06):

flavio commented on Issue #2373:

@torch2424 it's fine on Unix to have the STDIN -> 0, STDOUT -> 1 and STDERR -> 2. I'm not surprised by that :)

view this post on Zulip Wasmtime GitHub notifications bot (Nov 06 2020 at 23:08):

peterhuene edited a comment on Issue #2373:

Could it be this line that returns null when bytes read = 0 (i.e it always returns null because it'll read a 0 to indicate end of stream)?

view this post on Zulip Wasmtime GitHub notifications bot (Nov 06 2020 at 23:25):

sunfishcode commented on Issue #2373:

Yes, STDIN->0, STDOUT->1, STDERR->2 is true of WASI today, so it's fine to rely on for now.

That said, this is something that may change in the future, at the WASI level. The 0,1,2 values are required in POSIX so we'll always need a way to let applications that need this numbering to get it, but we may also want more flexibility for applications that don't need it.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 09 2020 at 22:06):

jedisct1 commented on Issue #2373:

Hi,

This is a misunderstanding of what the readAll() function does in as-wasi, and the behavior would be the same with any runtime.

The readAll() function reads a stream until the end. And a newline doesn't indicate the end of a stream.

stdin is an endless stream, unless it is manually closed from a console (Control-D), or the content of a file has been redirected to it (command < file.txt) and the whole file has been read.

In order to read a line of text, you need to read bytes until you reach a \n or \r\n sequence.

The current version of as-wasi includes a readLine() function (both in Descriptor and Console) that reads a line of text, and converts it into an AssemblyScript string. This is probably the function you should use here.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 09 2020 at 22:18):

peterhuene commented on Issue #2373:

Perhaps I misunderstood, but I don't think there was confusion over a newline causing a termination of the stream.

I think the problem is that @flavio was observing null returned even with a CTRL-D.

I believe this line is the cause, at least assuming that the stdin descriptor was opened correctly.

This code appears to buffer the stream until fd_read returns 0, at which point it returns null instead of the buffered input.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 09 2020 at 22:24):

peterhuene edited a comment on Issue #2373:

Perhaps I misunderstood, but I don't think there was confusion over a newline causing a termination of the stream.

I think the problem is that @flavio was observing null returned even with a CTRL-D.

I believe this line is the cause, at least assuming that the stdin descriptor was opened correctly.

This code appears to buffer the stream until fd_read returns 0, at which point it returns null instead of the buffered input.

Also, it should probably reset the read variable each iteration (or simply return null for an error returned by fd_read rather than the break) otherwise a successful read followed by an error will result in partial data being returned rather than null.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 09 2020 at 22:25):

peterhuene edited a comment on Issue #2373:

Perhaps I misunderstood, but I don't think there was confusion over a newline causing a termination of the stream.

I think the problem is that @flavio was observing null returned even with a CTRL-D.

I believe this line is the cause, at least assuming that the stdin descriptor was opened correctly.

This code appears to buffer the stream until fd_read returns 0 bytes read, at which point it returns null instead of the buffered input.

Also, it should probably reset the read variable each iteration (or simply return null for an error returned by fd_read rather than the break) otherwise a successful read followed by an error will result in partial data being returned rather than null.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 09 2020 at 22:31):

peterhuene edited a comment on Issue #2373:

Perhaps I misunderstood, but I don't think there was confusion over a newline causing a termination of the stream.

I think the problem is that @flavio was observing null returned from readAll even with a CTRL-D.

I believe this line is the cause, at least assuming that the stdin descriptor was opened correctly.

This code appears to buffer the stream until fd_read returns 0 bytes read, at which point it returns null instead of the buffered input.

Also, it should probably reset the read variable each iteration (or simply return null for an error returned by fd_read rather than the break) otherwise a successful read followed by an error will result in partial data being returned rather than null.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 10 2020 at 00:31):

jedisct1 commented on Issue #2373:

Since this is unrelated to wasmtime, maybe the issue should be discussed on the as-wasi repository instead?

view this post on Zulip Wasmtime GitHub notifications bot (Nov 10 2020 at 08:16):

flavio commented on Issue #2373:

I think the problem is that @flavio was observing null returned from readAll even with a CTRL-D.

Yes, exactly.

@jedisct1, sure if you want I can close this issue and open a new one one the as-wasi repository

view this post on Zulip Wasmtime GitHub notifications bot (Nov 19 2020 at 18:08):

peterhuene commented on Issue #2373:

Thanks for opening the issue there, @flavio. I'll close this issue for now in favor of jedisct1/as-wasi#95.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 19 2020 at 18:08):

peterhuene closed Issue #2373:

I hope I'm opening this bug on the right GitHub repo, if not please forgive me :sweat_smile:

I've written a simple "echo" program using AssemblyScript and as-wasi. The program reads the user input from STDIN and writes it back to STDOUT.

Unfortunately it looks like I can never get back the input I enter.

This the source code of the AssemblyScript program I'm running:

import "wasi"

import {Console} from "as-wasi"

Console.log("type something");

let input: string | null;
let msg : string = "nothing";

input = Console.readAll();
if (input != null) {
  msg = input!
}

Console.log('I got: ' + msg);

The program can be compiled to a WASM binary by doing:

$ asc echo.ts -b echo.wasm

And it can be run in this way:

$ wasmtime run echo.wasm

The program will start and I'll be able to enter my text. The program will keep reading from STDIN until I send the EOF symbol (I'm on Linux -> CTRL-D).

Unfortunately the input variable is always null.

I would expect the WASM program to be able to read data from stdin. The input object should hold the text I entered on my terminal.

This is my stack:

* wasmtime: 0.21.0
* AssemblyScript: 0.17.1
* as-wasi: 0.4.0

I'm running on a x86_64 Linux box that has openSUSE Tumbleweed

More information...

The as-wasi handles STDIN/STDOUT/STDERR by using instances of the Descriptor class. The library simply opens the file descriptor 0 for STDIN, 1 for STDOUT and 2 for STDERR. In my tests it looks like opening the file descriptor 0 always returns a null instance of Descriptor; this doesn't happen with STDOUT and STDERR.

The same issue happens also when running the program through a custom made Go program I wrote leveraging wasmtime-go.
In that case I even tried to start the WASM binary not by inheriting the parent STDIN, but instead by using a text file I previously created. Also in this case the WASM binary got a null object when reading from the STDIN.

Relevant: a similar WASM binary, generated by translating Rust -> WASM, just works as expected.

Thanks for any kind of help you can give me. I gotta say, WebAssembly and wasmtime are really cool :)


Last updated: Oct 23 2024 at 20:03 UTC