mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-05 11:33:04 +00:00
Leak pthreax_mutex_t when it's dropped while locked.
This commit is contained in:
parent
392d272868
commit
d72294491c
@ -1,5 +1,5 @@
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::mem::{forget, MaybeUninit};
|
||||
use crate::sys::cvt_nz;
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
|
||||
@ -23,6 +23,24 @@ impl LazyInit for Mutex {
|
||||
unsafe { mutex.init() };
|
||||
mutex
|
||||
}
|
||||
|
||||
fn destroy(mutex: Box<Self>) {
|
||||
// We're not allowed to pthread_mutex_destroy a locked mutex,
|
||||
// so check first if it's unlocked.
|
||||
if unsafe { mutex.try_lock() } {
|
||||
unsafe { mutex.unlock() };
|
||||
drop(mutex);
|
||||
} else {
|
||||
// The mutex is locked. This happens if a MutexGuard is leaked.
|
||||
// In this case, we just leak the Mutex too.
|
||||
forget(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
fn cancel_init(_: Box<Self>) {
|
||||
// In this case, we can just drop it without any checks,
|
||||
// since it cannot have been locked yet.
|
||||
}
|
||||
}
|
||||
|
||||
impl Mutex {
|
||||
|
@ -21,8 +21,21 @@ pub(crate) trait LazyInit {
|
||||
///
|
||||
/// It might be called more than once per LazyBox, as multiple threads
|
||||
/// might race to initialize it concurrently, each constructing and initializing
|
||||
/// their own box. (All but one of them will be destroyed right after.)
|
||||
/// their own box. All but one of them will be passed to `cancel_init` right after.
|
||||
fn init() -> Box<Self>;
|
||||
|
||||
/// Any surplus boxes from `init()` that lost the initialization race
|
||||
/// are passed to this function for disposal.
|
||||
///
|
||||
/// The default implementation calls destroy().
|
||||
fn cancel_init(x: Box<Self>) {
|
||||
Self::destroy(x);
|
||||
}
|
||||
|
||||
/// This is called to destroy a used box.
|
||||
///
|
||||
/// The default implementation just drops it.
|
||||
fn destroy(_: Box<Self>) {}
|
||||
}
|
||||
|
||||
impl<T: LazyInit> LazyBox<T> {
|
||||
@ -45,7 +58,7 @@ impl<T: LazyInit> LazyBox<T> {
|
||||
Err(ptr) => {
|
||||
// Lost the race to another thread.
|
||||
// Drop the box we created, and use the one from the other thread instead.
|
||||
drop(unsafe { Box::from_raw(new_ptr) });
|
||||
T::cancel_init(unsafe { Box::from_raw(new_ptr) });
|
||||
ptr
|
||||
}
|
||||
}
|
||||
@ -71,7 +84,7 @@ impl<T: LazyInit> Drop for LazyBox<T> {
|
||||
fn drop(&mut self) {
|
||||
let ptr = *self.ptr.get_mut();
|
||||
if !ptr.is_null() {
|
||||
drop(unsafe { Box::from_raw(ptr) });
|
||||
T::destroy(unsafe { Box::from_raw(ptr) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user