Skip to content
This repository has been archived by the owner on Mar 24, 2022. It is now read-only.

WASI fd_read from stdin works once (blocks) then immediately returns #128

Closed
kanaka opened this issue Apr 17, 2019 · 3 comments · Fixed by #148
Closed

WASI fd_read from stdin works once (blocks) then immediately returns #128

kanaka opened this issue Apr 17, 2019 · 3 comments · Fixed by #148

Comments

@kanaka
Copy link

kanaka commented Apr 17, 2019

This wat code:

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

  (memory 10)
  (export "memory" (memory 0))

  ;; prompt __wasi_ciovec_t struct
  (data (i32.const 0) "\08\00\00\00") ;; buf: pointer to prompt string
  (data (i32.const 4) "\02\00\00\00") ;; buf_len: 2 characters
  ;; string
  (data (i32.const 8) "> ")

  ;; read buf __wasi_ciovec_t struct
  (data (i32.const 16) "\18\00\00\00") ;; buf: pointer to string
  (data (i32.const 20) "\64\00\00\00") ;; buf_len: 100 characters max
  ;; string
  (data (i32.const 24) "\00") ;; buf (of 100 characters) to hold read in string

  (func $main (local i32)
    (loop $loop
      (drop (call $fd_write (i32.const 1) (i32.const 0) (i32.const 1) (i32.const 256)))
      (drop (call $fd_read (i32.const 0) (i32.const 16) (i32.const 1) (i32.const 256)))
      (drop (call $fd_write (i32.const 0) (i32.const 16) (i32.const 1) (i32.const 256)))
      (br $loop))
  )

  ;;(start $main)
  (export "_start" $main)
)

In wasmtime this works correctly reading and then printing what the user enters:

$ wasmtime wasitests/echo_loop.wasm
> foo
foo
> bar
bar
> ^C

In lucet, the first call to fd_read works, but each subsequent call immediately returns and the program loops rapidly printing the prompt:

# RUST_BACKTRACE=1 /opt/lucet/bin/lucet-wasi wasitests/echo_loop.so 
> foo
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ...
@jedisct1
Copy link
Contributor

Hi,

And sorry for the delayed response.

      (drop (call $fd_write (i32.const 0) (i32.const 16) (i32.const 1) (i32.const 256)))

The descriptor should probably be 1, not 0 here.

That being said, what happens here is that __wasi_fd_read(0...) returns __WASI_EBADF after the first read. This should obviously not be the case.

It only happens when stdin in a TTY. With a file, the descriptor remains valid.

I'm going to investigate why this happens. Thanks for your report!

@kanaka
Copy link
Author

kanaka commented Apr 19, 2019

@jedisct1 ah yes, I think that must have been a copy/paste from the previous line and I forgot to update the fd value. Thanks for looking into it.

For a little context, I'm trying to get the webassembly implementation of mal/make-a-lisp working across several runtimes. I've gotten it running in wasmtime and in my own runtimes (wac and warpy) but this was one of the issues I ran into trying to get it to run under lucet.

jedisct1 added a commit that referenced this issue Apr 23, 2019
fd_read() should not close the descriptor after a short read.

EOF is only reached when readv(2) returns 0.

Fixes #128
@kanaka
Copy link
Author

kanaka commented Apr 26, 2019

@jedisct1 I've built lucet with the change and confirmed that it is fixed for my use case. Now on to the next problem I discovered with mal/make-a-lisp: #158 :-)

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

Successfully merging a pull request may close this issue.

2 participants