Closed
Description
When running on a processor which support Intel's Restricted Transactional Memory, glibc will not write to a lock (making it appear to be unlocked) and instead begin a transaction. The transaction will catch any conflicts from other threads and aborts, but this doesn't happen when re-locking from the same thread. Instead the lock gets acquired twice, which results in two mutable references to the same value.
Example code:
use std::sync::{Mutex, RwLock};
fn test_mutex() -> i32 {
let m = Mutex::new(0);
let mut g = m.lock().unwrap();
let g2 = m.lock().unwrap();
*g = 1;
*g2
}
fn test_rwlock() -> i32 {
let m = RwLock::new(0);
let mut g = m.write().unwrap();
let g2 = m.write().unwrap();
*g = 1;
*g2
}
fn main() {
println!("{}", test_mutex());
println!("{}", test_rwlock());
}
Output:
$ ./test
1
1
For Mutex
, this can be solved by creating the mutex with pthread_mutexattr_settype(PTHREAD_MUTEX_NORMAL)
. However there is no way to disable this behavior for pthread rwlocks.