Skip to content

WASI libraries keep leaking memory #112749

Closed
@CryZe

Description

@CryZe

I tried this code:

#[no_mangle]
pub extern "C" fn update() {
    static FOO: std::sync::Once = std::sync::Once::new();
    FOO.call_once(|| {
        let _ = std::fs::metadata("/mnt/c/foo.txt");
    });
}

I expected to see this happen:

If you compile this to a WASI library and call the update function from a WASM runtime, then it will query the metadata of the file only during the first call to update. Every other invocation the update function should do nothing.

Instead, this happened:

The update function seems to refresh the list of preopened directories on every call... and it leaks them. The WASM memory keeps growing, looking like this:

image

This likely is because of the way Rust lazily initializes the list of preopened directories through wasi-libc. It probably does it unconditionally, which wasi-libc probably can't handle, so it never frees any memory.

The problem also occurs if you have any file system code at all, and it never even gets called:

#[no_mangle]
pub extern "C" fn other() {
    let _ = std::fs::metadata("/mnt/c/foo.txt");
}

#[no_mangle]
pub extern "C" fn update() { }

If you compile this code, but never call other and instead only update, it also keeps leaking the list of preopened directories.

The WASM seems to come down to this:

 (export "update" (func $update.command_export))
 ...
 (func $update.command_export
  (call $__wasm_call_ctors)
  (call $update)
  (call $__wasm_call_dtors)
 )

with

 (func $__wasm_call_ctors
  (call $__wasilibc_populate_preopens)
 )
 (func $__wasm_call_dtors
  (call $dummy)
  (call $dummy)
 )

__wasilibc_populate_preopens looks too complex. The original C code probably needs to be checked.

Meta

rustc --version --verbose:

rustc 1.70.0 (90c541806 2023-05-31)
binary: rustc
commit-hash: 90c541806f23a127002de5b4038be731ba1458ca
commit-date: 2023-05-31
host: x86_64-pc-windows-msvc
release: 1.70.0
LLVM version: 16.0.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-runtimeArea: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflowsC-bugCategory: This is a bug.I-memleakIssue: Runtime memory leak without `mem::forget`.O-wasmTarget: WASM (WebAssembly), http://webassembly.org/

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions