Add unsafe blocks in unsafe Thread::new · model-checking/verify-rust-std@7a0b2fb (original) (raw)
`@@ -22,36 +22,40 @@ pub struct Thread {
`
22
22
``
23
23
`impl Thread {
`
24
24
`// unsafe: see thread::Builder::spawn_unchecked for safety requirements
`
25
``
`-
#[allow(unsafe_op_in_unsafe_fn)]
`
26
``
`-
// FIXME: check the internal safety
`
27
25
`pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result {
`
28
26
`let p = Box::into_raw(Box::new(p));
`
29
27
``
30
28
`// CreateThread rounds up values for the stack size to the nearest page size (at least 4kb).
`
31
29
`// If a value of zero is given then the default stack size is used instead.
`
32
``
`-
let ret = c::CreateThread(
`
33
``
`-
ptr::null_mut(),
`
34
``
`-
stack,
`
35
``
`-
Some(thread_start),
`
36
``
`-
p as *mut _,
`
37
``
`-
c::STACK_SIZE_PARAM_IS_A_RESERVATION,
`
38
``
`-
ptr::null_mut(),
`
39
``
`-
);
`
40
``
`-
let ret = HandleOrNull::from_raw_handle(ret);
`
``
30
`` +
// SAFETY: thread_start
has the right ABI for a thread's entry point.
``
``
31
`` +
// p
is simply passed through to the new thread without being touched.
``
``
32
`+
let ret = unsafe {
`
``
33
`+
let ret = c::CreateThread(
`
``
34
`+
ptr::null_mut(),
`
``
35
`+
stack,
`
``
36
`+
Some(thread_start),
`
``
37
`+
p as *mut _,
`
``
38
`+
c::STACK_SIZE_PARAM_IS_A_RESERVATION,
`
``
39
`+
ptr::null_mut(),
`
``
40
`+
);
`
``
41
`+
HandleOrNull::from_raw_handle(ret)
`
``
42
`+
};
`
41
43
`return if let Ok(handle) = ret.try_into() {
`
42
44
`Ok(Thread { handle: Handle::from_inner(handle) })
`
43
45
`} else {
`
44
46
`// The thread failed to start and as a result p was not consumed. Therefore, it is
`
45
47
`// safe to reconstruct the box so that it gets deallocated.
`
46
``
`-
drop(Box::from_raw(p));
`
``
48
`+
unsafe { drop(Box::from_raw(p)) };
`
47
49
`Err(io::Error::last_os_error())
`
48
50
`};
`
49
51
``
50
52
`unsafe extern "system" fn thread_start(main: *mut c_void) -> u32 {
`
51
53
`// Next, reserve some stack space for if we otherwise run out of stack.
`
52
54
` stack_overflow::reserve_stack();
`
53
55
`// Finally, let's run some code.
`
54
``
`-
Box::from_raw(main as *mut Box<dyn FnOnce()>)();
`
``
56
`+
// SAFETY: We are simply recreating the box that was leaked earlier.
`
``
57
`` +
// It's the responsibility of the one who call Thread::new
to ensure this is safe to call here.
``
``
58
`+
unsafe { Box::from_raw(main as *mut Box<dyn FnOnce()>)() };
`
55
59
`0
`
56
60
`}
`
57
61
`}
`