Skip to content

Is mutex poisoning guaranteed to always work properly? #143471

Open
@purplesyringa

Description

@purplesyringa

Is this code sound?

// Represents an abstract type with safety invariants
struct Corruptee { is_corrupted: bool }
impl Corruptee {
    // SAFETY: must be non-corrupted
    unsafe fn witness_uncorrupted(&self) {
        unsafe { core::hint::assert_unchecked(!self.is_corrupted) }
    }
    fn corrupt(&mut self) { self.is_corrupted = true; }
    fn uncorrupt(&mut self) { self.is_corrupted = false; }
}

struct Worker {
    corruptee: Mutex<Corruptee>,
}

impl Worker {
    fn do_work(&self, f: impl FnOnce()) {
        let mut corruptee = self.corruptee.lock().expect("poisoned");
        // SAFETY: `corruptee` can only be corrupted if `f` has ever panicked, but if it did, the
        // mutex would be poisoned and `expect` would panic.
        unsafe {
            corruptee.witness_uncorrupted();
        }
        corruptee.corrupt();
        f();
        corruptee.uncorrupt();
    }
}

I'm aware that poisoning is advisory in the sense that anyone with access to the Mutex can remove the poison if they wish. But in this example, Mutex is never revealed to users of the safe abstraction, and is only used an implementation detail.

Do we want to guarantee that poisoning can be relied upon for safety, like in this example, and never has false negatives?

I'm asking because mutex poisoning doesn't always work currently. But it's also never explicitly documented to be best-effort.

@workingjubilee

@rustbot label +A-concurrency +C-discussion +T-libs-api

(If poisoning was considered reliable, this would be T-libs I-unsound.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-concurrencyArea: ConcurrencyC-discussionCategory: Discussion or questions that doesn't represent real issues.I-libs-api-nominatedNominated for discussion during a libs-api team meeting.I-libs-nominatedNominated for discussion during a libs team meeting.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions