Skip to content

Fix FDs becoming invalid once their file is unlinked#6467

Open
Arshia001 wants to merge 14 commits intowasmerio:mainfrom
Arshia001:fix/wasix-unlink
Open

Fix FDs becoming invalid once their file is unlinked#6467
Arshia001 wants to merge 14 commits intowasmerio:mainfrom
Arshia001:fix/wasix-unlink

Conversation

@Arshia001
Copy link
Copy Markdown
Member

@Arshia001 Arshia001 commented Apr 13, 2026

Fixes: #6360.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes cases where unlinking a file could invalidate existing open handles (FDs), aligning VirtualFile::unlink() behavior with expected POSIX-like semantics (path removed, handle remains usable until last close).

Changes:

  • Add lifecycle tracking to mem_fs inodes so unlinked files remain backed while handles are open, and are reclaimed on last-handle drop.
  • Adjust overlay_fs to support unlinking files opened from secondaries without breaking the open handle, including COW/unlink interactions.
  • Add new regression tests (Rust unit tests + WASIX C test + harness script) covering write/read after unlink.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/wasix/unlink-open-fd-write-after-unlink/run.sh Adds a WASIX test runner asserting expected stdout and host-volume behavior.
tests/wasix/unlink-open-fd-write-after-unlink/main.c New WASIX regression reproducer verifying handle validity across unlink + recreate.
lib/virtual-fs/src/overlay_fs.rs Adds SecondaryFile wrapper and updates COW unlink behavior; adds overlay-specific regression tests.
lib/virtual-fs/src/mem_fs/mod.rs Introduces FileLifecycle and threads it through inode node types.
lib/virtual-fs/src/mem_fs/filesystem.rs Centralizes unlink behavior via unlink_file_inode and updates tests for unlinked-but-open retention.
lib/virtual-fs/src/mem_fs/file_opener.rs Plumbs lifecycle into opened handles and newly created nodes.
lib/virtual-fs/src/mem_fs/file.rs Tracks handle open/close and reclaims storage on last-handle drop after unlink; expands tests.
lib/virtual-fs/src/lib.rs Clarifies VirtualFile::unlink() semantics in trait documentation.

Comment thread lib/virtual-fs/src/mem_fs/file_opener.rs Outdated
Comment thread lib/virtual-fs/src/mem_fs/file_opener.rs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment thread lib/virtual-fs/src/overlay_fs.rs
Comment thread lib/virtual-fs/src/mem_fs/mod.rs Outdated
Comment thread lib/virtual-fs/src/mem_fs/file_opener.rs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment thread lib/virtual-fs/src/overlay_fs.rs Outdated
Copy link
Copy Markdown
Member

@syrusakbary syrusakbary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@theduke will be better at reviewing this

Copy link
Copy Markdown
Collaborator

@theduke theduke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found two correctness issues in the new overlay unlink handling.

Comment thread lib/virtual-fs/src/overlay_fs.rs
Comment thread lib/virtual-fs/src/overlay_fs.rs
@artemyarulin
Copy link
Copy Markdown
Contributor

This PR seems like fixing that as well #6431

@Arshia001 Arshia001 enabled auto-merge (squash) April 30, 2026 08:22
@artemyarulin
Copy link
Copy Markdown
Contributor

@Arshia001 can you add a few unit tests to avoid regressions?

Here one Wasix (i've just created it before I've remembered about your PR :))

#include <assert.h>
#include <fcntl.h>
#include <unistd.h>

int main(void) {
  const char* path = "/tmp/wasix_fd_append_create_unlink_read.tmp";
  unlink(path);
  int fd = open(path, O_RDWR | O_APPEND | O_CREAT, 0600);
  assert(fd >= 0);
  assert(unlink(path) == 0);
  char buf;
  assert(read(fd, &buf, 1) == 0);
}

And the a second one from #6431 (probably need to be converted to C). It's important to have those to avoid future regressions

@artemyarulin
Copy link
Copy Markdown
Contributor

Shield - Regression 💩💩💩

Language Tests Pass rate now PASS FAIL TIMEOUT CRASH
Python 37,920 0.0% $${\color{red}-26105}$$ $${\color{red}+33083}$$ $${\color{green}-4911}$$ $${\color{green}-2}$$
Node.js 4,861 33.0% $${\color{green}+18}$$ $${\color{green}-70}$$ $${\color{red}+62}$$ $${\color{green}-9}$$
PHP 19,912 72.5% $${\color{red}-2}$$ $${\color{red}+2}$$ 0 0
Rust 22,337 94.3% $${\color{red}-1}$$ $${\color{green}-3}$$ 0 $${\color{red}+2}$$

Example crash from Rust

  • Repro command: shield run --lang rust --wasmer [WASMER BINARY] library::coretests::coretests-c583afeaf1b1870c
  • Full status file: tests_rust_results.json
crash: process: proc=000127 cwd=/home/runner/work/anti-regression-shield/anti-regression-shield env=RUST_BACKTRACE=full command=/home/runner/work/anti-regression-shield/anti-regression-shield/.work/wasmer/checkout/target/release/wasmer run --volume /home/runner/work/anti-regression-shield/anti-regression-shield/.work/rust/checkout:/home/runner/work/anti-regression-shield/anti-regression-shield/.work/rust/checkout --cwd /home/runner/work/anti-regression-shield/anti-regression-shield/.work/rust/checkout /home/runner/work/anti-regression-shield/anti-regression-shield/.cache/rust/wasmu/57fa1a714b832328.wasmu -- --test-threads=1
RuntimeError: unaligned atomic access
    at core::sync::atomic::AtomicBool::fetch_nand (coretests-3d2262867062fa53.wasm[14495]:0xffffffff)
    at coretests::atomic::atomic_access_bool (coretests-3d2262867062fa53.wasm[25901]:0xffffffff)
    at coretests::atomic::atomic_access_bool::{{closure}} (coretests-3d2262867062fa53.wasm[25900]:0xffffffff)
    at core::ops::function::FnOnce::call_once (coretests-3d2262867062fa53.wasm[7577]:0xffffffff)
    at test::__rust_begin_short_backtrace (coretests-3d2262867062fa53.wasm[27649]:0xffffffff)
    at test::types::RunnableTest::run (coretests-3d2262867062fa53.wasm[27680]:0xffffffff)
    at test::run_test (coretests-3d2262867062fa53.wasm[27644]:0xffffffff)
    at test::run_tests (coretests-3d2262867062fa53.wasm[27642]:0xffffffff)
    at test::console::run_tests_console (coretests-3d2262867062fa53.wasm[27478]:0xffffffff)
    at test::test_main (coretests-3d2262867062fa53.wasm[27634]:0xffffffff)
    at test::test_main_static (coretests-3d2262867062fa53.wasm[27635]:0xffffffff)
    at coretests::main (coretests-3d2262867062fa53.wasm[12082]:0xffffffff)
    at core::ops::function::FnOnce::call_once (coretests-3d2262867062fa53.wasm[8940]:0xffffffff)
    at std::sys::backtrace::__rust_begin_short_backtrace (coretests-3d2262867062fa53.wasm[15611]:0xffffffff)
    at std::rt::lang_start::{{closure}} (coretests-3d2262867062fa53.wasm[675]:0xffffffff)
    at std::rt::lang_start_internal (coretests-3d2262867062fa53.wasm[27950]:0xffffffff)
    at std::rt::lang_start (coretests-3d2262867062fa53.wasm[674]:0xffffffff)
    at __main_void (coretests-3d2262867062fa53.wasm[12083]:0xffffffff)
    at _start (coretests-3d2262867062fa53.wasm[136]:0xffffffff)

More changed tests

Install shield

  • git clone https://github.com/wasmerio/compat-tests.git
  • cd compat-tests
  • cargo build
  • ./target/debug/shield run --lang <LANG> --wasmer [WASMER BINARY] <TEST OR BATCH>

Artifacts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WASIX: fix writing to unlinked files with reference counting and POSIX-compliant unlink()/rmdir() API

5 participants