Open
Description
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.
@rustbot label +A-concurrency +C-discussion +T-libs-api
(If poisoning was considered reliable, this would be T-libs I-unsound.)