wasmer
wasmer copied to clipboard
[MemFS] `fstat` reports incorrect file information
fstat reports incorrect file information when the file is rewritten.
wasmer 2.2.1 | N/A | x86_64
Steps to reproduce
fstat reported outdated file info when a file is rewritten or deleted and created again.
main.c
extern void fstat_bug(void) {
int fd = open("/test.txt", O_RDONLY);
struct stat fileInfo = {0};
fstat(fd, &fileInfo);
printf("File size: %lld", fileInfo.st_size);
close(fd);
}
js
// Load WASM.
await init();
let wasi = new WASI({
env: {},
args: []
});
const moduleData = fetch(new URL('./main.wasm', import.meta.url));
const module = await WebAssembly.compileStreaming(moduleData);
const instance = await wasi.instantiate(module, {});
// 1️⃣ Create text.txt with 1 byte content.
const fileA = wasi.fs.open("/test.txt", { write: true, create: true, truncate: true });
fileA.writeString("a");
instance.exports.fstat_bug();
// ✅ File size should be 1.
console.log(wasi.getStdoutString()); // File size: 1
// 2️⃣ Remove text.txt
wasi.fs.removeFile("/test.txt");
// 3️⃣ Create a new text.txt with 3 bytes.
const fileAAA = wasi.fs.open("/test.txt", { write: true, create: true, truncate: true });
fileAAA.writeString("aaa");
instance.exports.fstat_bug();
// ❌ File size should be 3 but got 1.
console.log(wasi.getStdoutString()); // File size: 1
Expected behavior
fstat reports correct file size.
Actual behavior
fstat reports incorrect file size.
Additional context
-
If
fstatis called only once at the very end the result is correct. Looks like a cache invalidation issue?// 1️⃣ Create text.txt with 1 byte content. const fileA = wasi.fs.open("/test.txt", { write: true, create: true, truncate: true }); fileA.writeString("a"); // 2️⃣ Remove text.txt wasi.fs.removeFile("/test.txt"); // 3️⃣ Create a new text.txt with 3 bytes. const fileAAA = wasi.fs.open("/test.txt", { write: true, create: true, truncate: true }); fileAAA.writeString("aaa"); instance.exports.fstat_bug(); // ✅ File size should be 3. console.log(wasi.getStdoutString()); // File size: 3 -
The file's content can be read correctly.
After some investigation, I think this is related to how WasiFs and the js MemFS work.
MemFS (in wasmer-js package) operates the fs_backing of the WasiFs directly. When a file is updated by MemFS, its cache (WasiFs.inodes) in WasiFs does not update.
A naive approach to fix the file size issue is to call state.fs.filestat_resync_size(out_fd) in the end of pub fn path_open.
// wasi/src/syscalls/mod.rs
pub fn path_open(...) {
...
let out_fd = wasi_try!(state.fs.create_fd(
adjusted_rights,
fs_rights_inheriting,
fs_flags,
open_flags,
inode
));
state.fs.filestat_resync_size(out_fd);
fd_cell.set(out_fd);
...
}
However I don't think this solves the main problem. File operations like remove, rename, etc., should also be synced and fixes like this are error-prone.
Maybe it's better to let MemFS call methods of WasiFs instead of directly use its backing fs, or create a more robust synchronization mechanism.
Thanks for the bug report! This seems to be an issue in the file system. This requires further investigation. We would like to keep WasiFS and MemFS separated, they should not rely on each other. Would you like to help us resolve this?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Should check if this is still relevant.