@@ -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 < Thread > {
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
}
0 commit comments