提交 184d3b3b 编写于 作者: R Ralf Jung

expand thread-local storage tests to cover dtor order and re-running dtors

上级 d539fafa
......@@ -614,7 +614,7 @@ fn call_c_abi(
let arg_dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
self.write_primval(arg_dest, data, u8_ptr_ty)?;
// We ourselbes return 0
// We ourselves return 0
self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
// Don't fall through
......
//ignore-windows
#![feature(libc)]
extern crate libc;
use std::mem;
pub type Key = libc::pthread_key_t;
pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
let mut key = 0;
assert_eq!(libc::pthread_key_create(&mut key, mem::transmute(dtor)), 0);
key
}
fn main() {
let _ = unsafe { create(None) };
}
//ignore-windows
#![feature(libc)]
extern crate libc;
use std::mem;
pub type Key = libc::pthread_key_t;
static mut RECORD : usize = 0;
static mut KEYS : [Key; 2] = [0; 2];
static mut GLOBALS : [u64; 2] = [1, 0];
static mut CANNARY : *mut u64 = 0 as *mut _; // this serves as a cannary: if TLS dtors are not run properly, this will not get deallocated, making the test fail.
pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
let mut key = 0;
assert_eq!(libc::pthread_key_create(&mut key, mem::transmute(dtor)), 0);
key
}
pub unsafe fn set(key: Key, value: *mut u8) {
let r = libc::pthread_setspecific(key, value as *mut _);
assert_eq!(r, 0);
}
pub fn record(r: usize) {
assert!(r < 10);
unsafe { RECORD = RECORD*10 + r };
}
unsafe extern fn dtor(mut ptr: *mut u64) {
assert!(CANNARY != 0 as *mut _); // make sure we do not get run too often
let val = *ptr;
let which_key = GLOBALS.iter().position(|global| global as *const _ == ptr).expect("Should find my global");
record(which_key);
if val > 0 {
*ptr = val-1;
set(KEYS[which_key], ptr as *mut _);
}
// Check if the records matches what we expect. If yes, clear the cannary.
// If the record is wrong, the cannary will ever get cleared, leading to a leak -> test fails.
// If the record is incomplete (i.e., more dtor calls happen), the check at the beginning of this function will fail -> test fails.
// The correct sequence is: First key 0, then key 1, then key 0.
if RECORD == 0_1_0 {
drop(Box::from_raw(CANNARY));
CANNARY = 0 as *mut _;
}
}
fn main() {
unsafe {
create(None); // check that the no-dtor case works
// Initialize the keys we use to check destructor ordering
for (key, global) in KEYS.iter_mut().zip(GLOBALS.iter()) {
*key = create(Some(mem::transmute(dtor as unsafe extern fn(*mut u64))));
set(*key, global as *const _ as *mut _);
}
// Initialize cannary
CANNARY = Box::into_raw(Box::new(0u64));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册