Skip to content

Commit fc38388

Browse files
committed
Add functions to un-poison Mutex and RwLock
See discussion at https://internals.rust-lang.org/t/unpoisoning-a-mutex/16521/3
1 parent 9ea4d41 commit fc38388

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

library/std/src/sync/mutex.rs

+34
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,40 @@ impl<T: ?Sized> Mutex<T> {
363363
self.poison.get()
364364
}
365365

366+
/// Clear the poisoned state from a mutex
367+
///
368+
/// If the mutex is poisoned, it will remain poisoned until this function is called
369+
/// with a mutex guard. This allows recovering from a poisoned state and marking
370+
/// that it has recovered. For example, if the value is overwritten by a known-good value,
371+
/// then the mutex can be marked as un-poisoned. Or possibly, the value could be inspected to
372+
/// determine if it is in a consistent state, and if so the poison is removed.
373+
///
374+
/// # Examples
375+
///
376+
/// ```
377+
/// #![feature(mutex_unpoison)]
378+
///
379+
/// use std::sync::{Arc, Mutex};
380+
/// use std::thread;
381+
///
382+
/// let mutex = Arc::new(Mutex::new(0));
383+
/// let c_mutex = Arc::clone(&mutex);
384+
///
385+
/// let _ = thread::spawn(move || {
386+
/// let _lock = c_mutex.lock().unwrap();
387+
/// panic!(); // the mutex gets poisoned
388+
/// }).join();
389+
///
390+
/// let guard = mutex.lock().unwrap_err().into_inner();
391+
/// Mutex::clear_poison(&guard);
392+
/// assert_eq!(mutex.is_poisoned(), false);
393+
/// ```
394+
#[inline]
395+
#[unstable(feature = "mutex_unpoison", issue = "none")]
396+
pub fn clear_poison(guard: &MutexGuard<'_, T>) {
397+
guard.lock.poison.clear();
398+
}
399+
366400
/// Consumes this mutex, returning the underlying data.
367401
///
368402
/// # Errors

library/std/src/sync/poison.rs

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ impl Flag {
4040
pub fn get(&self) -> bool {
4141
self.failed.load(Ordering::Relaxed)
4242
}
43+
44+
#[inline]
45+
pub fn clear(&self) {
46+
self.failed.store(false, Ordering::Relaxed)
47+
}
4348
}
4449

4550
pub struct Guard {

library/std/src/sync/rwlock.rs

+34
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,40 @@ impl<T: ?Sized> RwLock<T> {
366366
self.poison.get()
367367
}
368368

369+
/// Clear the poisoned state from a lock
370+
///
371+
/// If the lock is poisoned, it will remain poisoned until this function is called
372+
/// with a write guard. This allows recovering from a poisoned state and marking
373+
/// that it has recovered. For example, if the value is overwritten by a known-good value,
374+
/// then the mutex can be marked as un-poisoned. Or possibly, the value could be inspected to
375+
/// determine if it is in a consistent state, and if so the poison is removed.
376+
///
377+
/// # Examples
378+
///
379+
/// ```
380+
/// #![feature(mutex_unpoison)]
381+
///
382+
/// use std::sync::{Arc, RwLock};
383+
/// use std::thread;
384+
///
385+
/// let lock = Arc::new(RwLock::new(0));
386+
/// let c_lock = Arc::clone(&lock);
387+
///
388+
/// let _ = thread::spawn(move || {
389+
/// let _lock = c_lock.write().unwrap();
390+
/// panic!(); // the mutex gets poisoned
391+
/// }).join();
392+
///
393+
/// let guard = lock.write().unwrap_err().into_inner();
394+
/// RwLock::clear_poison(&guard);
395+
/// assert_eq!(lock.is_poisoned(), false);
396+
/// ```
397+
#[inline]
398+
#[unstable(feature = "mutex_unpoison", issue = "none")]
399+
pub fn clear_poison(guard: &RwLockWriteGuard<'_, T>) {
400+
guard.lock.poison.clear();
401+
}
402+
369403
/// Consumes this `RwLock`, returning the underlying data.
370404
///
371405
/// # Errors

0 commit comments

Comments
 (0)