Open alexrp opened 4 months ago
Just to clarify, what's the host system? Context: https://github.com/ziglang/zig/issues/13157
❯ uname -srm
Linux 6.5.0-44-generic x86_64
This could very easily be a bug in wasmtime
. From the POSIX specificaiton of open
:
[EISDIR]
The named file is a directory and oflag includes O_WRONLY or O_RDWR.
This is actually pretty likely to be a bug in wasmtime
, and it's one that manifested in exactly the same way in the past (but was fixed, so this seems like a regression):
EDIT: I'm not so certain that this is the same bug, I was doing something dumb while testing.
Seems to be related to wasi-libc
:
Without linking libc, the tests pass:
$ zig test lib/std/std.zig --zig-lib-dir lib -target wasm32-wasi -femit-bin=test-wasi.wasm --test-no-exec
$ wasmtime --dir=. test-wasi.wasm
2592 passed; 115 skipped; 0 failed.
When linking libc, that test fails:
$ zig test lib/std/std.zig --zig-lib-dir lib -target wasm32-wasi -femit-bin=test-wasi-libc.wasm -lc --test-no-exec
$ wasmtime --dir=. test-wasi-libc.wasm
...
expected error.IsDir, found fs.File{ .handle = 7 }
1192/2707 fs.test.test.file operations on directories...FAIL (TestUnexpectedError)
Unable to dump stack trace: not implemented for Wasm
...
2589 passed; 117 skipped; 1 failed.
EDIT: The first wasmtime
version that fails is 15.0.0
:
$ ~/Downloads/wasmtime-v15.0.0-x86_64-linux/wasmtime --dir=. test-wasi-libc.wasm
2589 passed; 117 skipped; 1 failed.
$ ~/Downloads/wasmtime-v14.0.4-x86_64-linux/wasmtime --dir=. test-wasi-libc.wasm
2590 passed; 117 skipped; 0 failed.
The plot thickens...
The following test cases are built/run with
$ zig test open-dir-rw.zig -target wasm32-wasi -lc -femit-bin=open-dir-rw-test-libc.wasm --test-no-exec
$ wasmtime --dir=. open-dir-rw-test-libc.wasm
// This fails:
test "file operations on directories in tmpDir" {
var tmp_dir = testing.tmpDir(.{});
defer tmp_dir.cleanup();
const test_dir_name = "testdir";
try tmp_dir.dir.makeDir(test_dir_name);
try testing.expectError(error.IsDir, tmp_dir.dir.openFile(test_dir_name, .{ .mode = .read_write }));
}
// But this passes:
test "file operations on directories in cwd" {
const test_dir_name = "testdir";
try std.fs.cwd().deleteTree(test_dir_name);
try std.fs.cwd().makeDir(test_dir_name);
try testing.expectError(error.IsDir, std.fs.cwd().openFile(test_dir_name, .{ .mode = .read_write }));
}
So somehow the usage of tmpDir
is involved in the failure.
Found a reproduction with wasi-sdk 23.0
, so this is indeed an upstream wasi-libc
/wasmtime
bug:
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
mkdirat(AT_FDCWD, "testdir", 0777);
{
// Opening with O_RDWR fails as expected if the dir fd is AT_FDCWD
int dir = openat(AT_FDCWD, "testdir", O_RDWR);
if (dir != -1) return 1;
}
// Open "testdir" for real now since we want to use it as the fd for openat
int dir = openat(AT_FDCWD, "testdir", O_RDONLY|O_DIRECTORY);
mkdirat(dir, "subdir", 0777);
// Try to open the subdir with O_RDWR, this should fail but it succeeds
// because the O_RDWR is lost and the openat2 syscall is called with O_RDONLY
// instead
int testdir = openat(dir, "subdir", O_RDWR);
if (testdir != -1) return 1;
return 0;
}
$ WASI_SDK=/home/ryan/Downloads/wasi-sdk-23.0-x86_64-linux
$ $WASI_SDK/bin/clang --sysroot=$WASI_SDK/share/wasi-sysroot open-dir-tmpdir-rw.c -o open-dir-tmpdir-rw-sdk-23.wasm
$ strace -e trace=openat2 wasmtime --dir=. open-dir-tmpdir-rw-sdk-23.wasm
openat2(3, "testdir", {flags=O_RDWR|O_LARGEFILE|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = -1 EISDIR (Is a directory)
openat2(3, "testdir", {flags=O_RDONLY|O_LARGEFILE|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 11
openat2(11, "subdir", {flags=O_RDONLY|O_LARGEFILE|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 12
+++ exited with 1 +++
The O_RDWR
is lost when calling openat
with an fd
that's not AT_FDCWD
.
EDIT: Created a wasmtime
issue: https://github.com/bytecodealliance/wasmtime/issues/9054
Zig Version
1fc42ed3e7ca0b74b54aaa827276d995d6c7c6cd
Steps to Reproduce and Observed Behavior
-fwasmtime
(but see #20745).Fails here: https://github.com/ziglang/zig/blob/eac7fd4da5992299a1f2fb59c5aa237c0c6c6761/lib/std/fs/test.zig#L767-L769
Expected Behavior
No failure.