wasmer: `fflush` doesn't work on WASI

Describe the bug

fflush provided by wasi-sdk doesn’t work on wasmer.

wasmer -vV; rustc -vV
wasmer 3.2.0 (8a343d0 2023-04-18)
binary: wasmer-cli
commit-hash: 8a343d0f9a1d3d4b4bfe622ed345253d780a3d76
commit-date: 2023-04-18
host: x86_64-unknown-linux-gnu
compiler: singlepass,cranelift,llvm
sh: 1: rustc: not found

Steps to reproduce

sample C program:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
  char buf[5];
  int len = 5, ret;

  printf("input something\n");
  printf("> ");
  fflush(stdout);
  ret = read(0, buf, len);
  if (ret > 0) {
    printf("got %.*s (first 5 chars)\n", ret, buf);
  }
  return 0;
}

I built this using wasi-sdk 19.0. (${WASI_SDK_PATH}/bin/clang --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -o out.wasm main.c)

On host, prompt (>) is printed by fflush.

$ gcc main.c ; ./a.out
input something
> hi
got hi
 (first 5 chars)

On wasmer, prompt (>) isn’t printed (isn’t flushed).

$ wasmer /app/out.wasm
input something

Expected behavior

fflush works and buffered strings are printed.

Actual behavior

fflush doesn’t work and buffered strings aren’t printed.

Additional context

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 17 (14 by maintainers)

Most upvoted comments

@ibrahim-akrab please take over, I am too busy right now to deal with the urgency.

Thanks.

@mucinoab we are waiting for some testing code. Please add it quickly or we will resolve the ticket ourself and the bounty will not be distributed.

It is triggering the write syscall at the specific point in program execution. And that’s it’s sole job, to make sure anything left in the buffer gets passed to a write syscall. So it’s working as intended.

What’s not working as intended is wasmers fd_write since at the end of a syscall, we should be sure buffer data is all written from memory to the specific file handler. Of course that’s not what happens.

The current implementation leaves it to the compiler to decide when to write the data to the file, instead of choosing manually when to write to make it compatible with native binary’s execution

@theduke The thing is that every write syscall is a flushing write. You can’t expect to tell the kernel to write to a file then it keeps that piece of information around until you flush it (somehow).

Writing then flushing is an abstraction layer provided by programming languages in order to have control over when the actual syscall is called.

That’s why the wasmer implementation of fd_write should flush on every write in order to behave like native binaries.