Check the file type after open() in Dir.openFile() when using WASI#15824
Check the file type after open() in Dir.openFile() when using WASI#15824jedisct1 wants to merge 1 commit intoziglang:masterfrom
Conversation
When the `O_DIRECTORY` flag is not present, Wasmtime now opens files and directories the same way, and returns a descriptor in any case. So, explicitly check the file type after opening it, and return `err.IsDir` if what we actually have is a directory. Fixes the `lib/std/fs` `"file operations on directories"` test on WASI with Wasmtime 9.0.0
|
I would guess that wasmtime behaves differently here on Windows vs non-Windows (i.e. I don't think the I'm having a very hard time navigating wasmtime/wasi spec/etc to understand if/where this behavior is specified, why it changed, how it changed, etc. My naive first impression is that it seems like it'd be a wasmtime/wasi spec bug, assuming at least that wasmtime wants each host platform to behave the same; from #13157 (comment):
|
|
Here is where the change may have been introduced. I think the intent was to be In line with how |
|
Thanks for the link, that makes sense. I was wrong about Windows needing file or directory specified in its open calls; see d3f87f8. Perhaps the wasi spec would be interested in a |
|
Also related: #5732 Lines 458 to 460 in a0652fb I wonder if this would be considered a wasmtime bug, in that it seems like it's allowing opening directories for writing. EDIT: Actually, why isn't the |
|
I can't reproduce the $ wasmtime --version
wasmtime-cli 9.0.1
$ zig version
0.11.0-dev.3277+a0652fb93
$ zig test --zig-lib-dir lib --main-pkg-path lib/std -target wasm32-wasi --test-cmd wasmtime --test-cmd --dir=. --test-cmd-bin lib/std/std.zig
...
1106/2505 test.file operations on directories... OK
...
2354 passed; 151 skipped; 0 failed. |
|
Still failing for me with wasmtime 9.0.1: |
|
Is that the intended behavior, or a wasmtime bug? /cc @jameysharp |
|
I don't understand what this test is trying to do, and I also don't understand WASI very well, either in spec or in implementation. So I don't know how to answer that question. I do think the idea of a And I'm curious about this as well:
|
|
@jameysharp The test opens a directory (without I think this is a recent change. On CI which is still running Wasmtime 2.0.2, the test passes. |
|
The failure is related to linking libc. I can reproduce it if I add |
|
EDIT: This comment can be ignored (only the "Here's how I'm testing" part is relevant), see the next comment for better info Looks like // notes: 0x1b5 = 437 which is openat2, 0x3 is the cwd's fd, 0x18 is sizeof(struct open_how)
syscall_0x1b5(0x3, 0x7ffe0db39fc8, 0x7ffe0db39f68, 0x18, 0, 0) = 0x5According to the openat2 docs, all the possible errors of Here's how I'm testing: // open-dir-rw.zig
const std = @import("std");
pub fn main() !void {
const test_dir_name = "testdir";
try std.fs.cwd().makePath("testdir");
try std.testing.expectError(error.IsDir, std.fs.cwd().openFile(test_dir_name, .{ .mode = .read_write }));
}or with strace EDIT: Here's the relevant line from So most likely EDIT#2: I think this is as far as I can go for now. My debugging skills are not up to par for this task, but hopefully this is enough of a starting point that someone with better debugging skills can figure out what's happening here. |
|
Updated With openat2(3, "testdir", {flags=O_RDONLY|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 5Without openat2(3, "testdir", {flags=O_RDWR|O_APPEND|O_NOFOLLOW|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = -1 EISDIR (Is a directory)(stack trace is the same as above) EDIT: Note also that changing EDIT: The bug doesn't seem to be on the Zig side. If I add std.debug.print("openatZ RDWR={}\n", .{flags & O.RDWR == O.RDWR});before this line: Line 1734 in bfe02ff then it prints: EDIT#2: The equivalent C program compiled to wasm exhibits the same (buggy) behavior: #include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main() {
int rc = openat(AT_FDCWD, "testdir", O_RDWR);
return 0;
}EDIT#3: Can also reproduce this with $ strace -e trace=openat2 wasmtime --dir=. open-dir-rw-c-sdk.wasm
openat2(3, "testdir", {flags=O_RDONLY|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 5EDIT#4: Made a |
|
The test is failing since this exact commit in |
|
This is actually a bug in Wasmtime: bytecodealliance/wasmtime#6462 And more importantly, they are planning to released a fixed version soon, so we don't need the extra That was also a good reminder that we should constantly keep Thanks a lot @squeek502 for your help and investigation! |
When the
O_DIRECTORYflag is not present, Wasmtime now opens files and directories the same way, and returns a descriptor in any case.So, explicitly check the file type after opening it, and return
err.IsDirif what we actually have is a directory.Fixes the
lib/std/fs"file operations on directories"test on WASI with Wasmtime 9.0.0