File tree Expand file tree Collapse file tree 1 file changed +16
-13
lines changed
library/std/src/sys/thread_local/destructors Expand file tree Collapse file tree 1 file changed +16
-13
lines changed Original file line number Diff line number Diff line change @@ -8,7 +8,7 @@ static REENTRANT_DTOR: Cell<Option<(*mut u8, unsafe extern "C" fn(*mut u8))>> =
88static DTORS : RefCell < Vec < ( * mut u8 , unsafe extern "C" fn ( * mut u8 ) ) > > = RefCell :: new ( Vec :: new ( ) ) ;
99
1010pub unsafe fn register ( t : * mut u8 , dtor : unsafe extern "C" fn ( * mut u8 ) ) {
11- // Borrow DTORS can only fail if the global allocator calls this
11+ // Borrowing DTORS can only fail if the global allocator calls this
1212 // function again.
1313 if let Ok ( mut dtors) = DTORS . try_borrow_mut ( ) {
1414 guard:: enable ( ) ;
@@ -33,18 +33,21 @@ pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
3333pub unsafe fn run ( ) {
3434 loop {
3535 let mut dtors = DTORS . borrow_mut ( ) ;
36- match dtors. pop ( ) {
37- Some ( ( t, dtor) ) => {
38- drop ( dtors) ;
39- unsafe {
40- dtor ( t) ;
41- }
42- }
43- None => {
44- // Free the list memory.
45- * dtors = Vec :: new ( ) ;
46- break ;
47- }
36+ let Some ( ( t, dtor) ) = dtors. pop ( ) else { break } ;
37+
38+ // If the global allocator has allocated a thread-local variable
39+ // it will always be the first in the dtors list (if an alloc came
40+ // before the first regular register()), or be the REENTRANT_DTOR
41+ // (if a register() came before the first alloc). In the former
42+ // case we have to make sure not to touch the global (de)allocator again
43+ // on this thread, so free dtors now, before calling the last dtor.
44+ if dtors. is_empty ( ) {
45+ * dtors = Vec :: new ( ) ;
46+ }
47+
48+ drop ( dtors) ;
49+ unsafe {
50+ dtor ( t) ;
4851 }
4952 }
5053
You can’t perform that action at this time.
0 commit comments