wasmerio/wasmer · critical

The linker state's lock is poisoned

Error message

The linker state's lock is poisoned

What it means

`write_linker_state` acquires the shared `LinkerState` RwLock via a `try_write` loop with backoff and cooperative DL draining. `RwLock` locks are poisoned when a thread panics while holding the lock; instead of propagating poisoning, this path deliberately panics with this message, indicating that some earlier code panicked while the linker state write lock was held and the linker's shared state can no longer be trusted.

Source

Thrown at lib/wasix/src/state/linker/sync/linker_shared.rs:133

    /// paths: another OS thread might hold the write lock while follower groups rendezvous at a DL
    /// barrier waiting for **this** thread to run [`Self::do_pending_link_operations_internal`].
    pub(in crate::state::linker) fn write_linker_state(
        &self,
        group_state: &mut InstanceGroupState,
        ctx: &mut FunctionEnvMut<'_, WasiEnv>,
    ) -> Result<RwLockWriteGuard<'_, LinkerState>, LinkError> {
        let mut linker_write_backoff = LinkerStateWriteBackoff::new();
        loop {
            match self.linker_state.try_write() {
                Ok(guard) => return Ok(guard),
                Err(std::sync::TryLockError::WouldBlock) => {
                    linker_write_backoff.backoff();
                    let env = ctx.as_ref();
                    let mut store = ctx.as_store_mut();
                    self.do_pending_link_operations_internal(group_state, &mut store, &env)?;
                }
                Err(std::sync::TryLockError::Poisoned(_)) => {
                    panic!("The linker state's lock is poisoned");
                }
            }
        }
    }

    /// [`TopologyCoordinator::try_acquire`] loop with [`LinkerStateWriteBackoff`] plus cooperative drains
    /// of [`Self::do_pending_link_operations_internal`].
    ///
    /// **Lock ordering**: topology must be leased **before** taking [`LinkerState`] for write paths that
    /// change replicated topology (spawn prepare, guarded loads, [`super::super::Linker::resolve_export`],
    /// etc.).
    ///
    /// `prepare_for_instance_group` is the motivating case — the parent attaches no new subscribers until
    /// the child finalizes while still holding this token handed across threads.
    pub(in crate::state::linker) fn acquire_topology_token(
        &self,
        group_state: &mut InstanceGroupState,
        store: &mut impl AsStoreMut,

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Fix the original panic that poisoned the lock — look for the first panic/backtrace in the logs, not this secondary one
  2. Ensure code holding the linker write lock cannot panic (avoid `unwrap`, validate bus capacities, follow the linker `sync` module lock-ordering docs)
  3. Restart the affected WASIX process/module tree — poisoned linker state is not recoverable by design
  4. Use `catch_unwind` at the embedding boundary to contain panics so the process can be torn down cleanly instead of leaving poisoned locks for other threads
Defensive patterns

Strategy: try-catch

Try / catch

// Contain panics so the linker lock isn't left poisoned for other threads
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    linker.write_linker_state(&mut group_state, &mut ctx)?
}));
match result {
    Ok(guard) => { /* proceed */ }
    Err(_) => { /* tear down the whole WASIX process; lock is poisoned */ }
}

Prevention

When it happens

Trigger: Any earlier panic while a thread held the `LinkerState` write lock (e.g. one of the DL bus invariant panics in `synchronize_link_operation` or a syscall panic under lock), followed by another thread calling `write_linker_state` and hitting `TryLockError::Poisoned`.

Common situations: Multi-threaded WASIX workloads where one worker crashed inside a dynamic-link operation while holding the linker write lock; secondary panics in sibling threads after the original failure; embedding wasix in a server where instance groups share one linker across OS threads.

Related errors


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/86a26f4c2a1e88a4. Report an issue: GitHub.