Description
Not sure if anything needs to be done about this, since I don't know of any actual implementations having a problem with it, but it occurred to me when thinking about moving mutexes.
On Unix, Mutex::new
corresponds to initialization with PTHREAD_MUTEX_INITIALIZER
; Mutex::lock
, which returns a MutexGuard
, corresponds to pthread_mutex_lock
; MutexGuard::drop
corresponds to pthread_mutex_unlock
; and Mutex::drop
corresponds to pthread_mutex_destroy
.
If a MutexGuard
is forgotten:
use std::sync::Mutex;
use std::mem::forget;
fn main() {
let mutex: Mutex<()> = Mutex::new(());
let guard = mutex.lock();
forget(guard);
}
...then we call pthread_mutex_destroy
without first calling pthread_mutex_unlock
. The POSIX spec says:
It shall be safe to destroy an initialized mutex that is unlocked. Attempting to destroy a locked mutex or a mutex that is referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread results in undefined behavior.