wasmerio / wasmer

🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten
https://wasmer.io
MIT License
18.2k stars 767 forks source link

Named pipe file type isn't set correctly in `st_mode` in stat #4811

Open bbb651 opened 3 weeks ago

bbb651 commented 3 weeks ago

Describe the bug

The resulting stat struct after fstat never have the mode set to named pipe ((stat.st_mode & libc::S_IFMT) == libc::S_IFIFO) when it should.

wasmer 4.3.0 (??????? 1970-01-01)
binary: wasmer-cli
commit-hash:
commit-date: 1970-01-01
host: x86_64-unknown-linux-gnu
compiler: singlepass,cranelift
rustc 1.78.0 (9b00956e5 2024-04-29)
binary: rustc
commit-hash: 9b00956e56009bab2aa15d7bff10916599e3d6d6
commit-date: 2024-04-29
host: x86_64-unknown-linux-gnu
release: 1.78.0
LLVM version: 18.1.2

Steps to reproduce

Compile the following program with cargo b --target=wasm32-wasip1

use std::{
    env,
    io::stdin,
    mem,
    os::fd::AsRawFd,
    process::exit,
};

fn main() {
    let stdin = stdin();
    let stat = unsafe {
        let mut stat = mem::zeroed();
        libc::fstat(stdin.as_raw_fd(), &mut stat);
        stat
    };
    dbg!(&stat);
    if (stat.st_mode & libc::S_IFMT) != libc::S_IFIFO {
        let name = env::args().next().unwrap();
        eprintln!(r#"Usage: echo -e "a\nb" | {name}"#);
        exit(1);
    }
    let strings: Vec<String> = stdin.lines().filter_map(Result::ok).collect();
    dbg!(&strings);
}

Run it with piped input, e.g. echo -e "a\nb" | wasmer run ./target/wasm32-wasip1/debug/example.wasm

Expected behavior

I expect st_mode will have the type set as named pipe ((stat.st_mode & libc::S_IFMT) != libc::S_IFIFO will evaluate to false), and the program will print the lines from the input and exit with status code 0.

This is what happens when compiling it to linux:

❯ echo -e "a\nb" | ./target/debug/example
[src/main.rs:18:5] &stat = stat {
    st_dev: 15,
    st_ino: 217265,
    st_nlink: 1,
    st_mode: 4480,
    st_uid: 1000,
    st_gid: 1000,
    __pad0: 0,
    st_rdev: 0,
    st_size: 0,
    st_blksize: 4096,
    st_blocks: 0,
    st_atime: 1717612422,
    st_atime_nsec: 602921376,
    st_mtime: 1717612422,
    st_mtime_nsec: 602921376,
    st_ctime: 1717612422,
    st_ctime_nsec: 602921376,
    __unused: [
        0,
        0,
        0,
    ],
}
[src/main.rs:28:5] &strings = [
    "a",
    "b",
]

Actual behavior

The file type isn't set as named pipe like it should ((stat.st_mode & libc::S_IFMT) != libc::S_IFIFO is always true):

❯ echo "a\nb" | wasmer ./target/wasm32-wasip1/debug/example.wasm
[src/main.rs:18:5] &stat = stat {
    st_dev: 0,
    st_ino: 2,
    st_nlink: 1,
    st_mode: 8192,
    st_uid: 0,
    st_gid: 0,
    __pad0: 0,
    st_rdev: 0,
    st_size: 0,
    st_blksize: 0,
    st_blocks: 0,
    st_atim: timespec {
        tv_sec: 0,
        tv_nsec: 0,
    },
    st_mtim: timespec {
        tv_sec: 0,
        tv_nsec: 0,
    },
    st_ctim: timespec {
        tv_sec: 0,
        tv_nsec: 0,
    },
    __reserved: [
        0,
        0,
        0,
    ],
}
Usage: echo -e "a\nb" | ./target/wasm32-wasip1/debug/example.wasm

Additional context

This also happens on wasmtime. Maybe this is a limitation with the wasi interface?

syrusakbary commented 3 weeks ago

If it works properly in native (POSIX) but not in wasi is very likely a bug. We'll investigate

bbb651 commented 3 weeks ago

Can confirm this is an issue with wasmer (and wasmtime), as it works as expected with iwasm and wasm3 (I'm starting to have a concerning amount of wasm runtimes installed on my system :p)