@@ -72,6 +72,7 @@ use std::io::Error;
72
72
use std:: mem;
73
73
#[ cfg( not( windows) ) ]
74
74
use std:: ptr;
75
+ use std:: sync:: atomic:: { AtomicPtr , Ordering } ;
75
76
// Once::new is now a const-fn. But it is not stable in all the rustc versions we want to support
76
77
// yet.
77
78
#[ allow( deprecated) ]
@@ -171,20 +172,20 @@ impl Slot {
171
172
// There doesn't seem to be a way to make Cargo force the dependency for only one target
172
173
// (it doesn't compile the ones it doesn't need, but it stills considers the other targets
173
174
// for version resolution).
174
- //
175
+ //
175
176
// Therefore, we let the user have freedom - if they want AIX, they can upgrade to new
176
177
// enough libc. If they want ancient rustc, they can force older versions of libc.
177
178
//
178
179
// See #169.
179
180
180
181
new. sa_sigaction = handler as usize ; // If it doesn't compile on AIX, upgrade the libc dependency
181
-
182
+
182
183
// Android is broken and uses different int types than the rest (and different depending on
183
184
// the pointer width). This converts the flags to the proper type no matter what it is on
184
185
// the given platform.
185
186
#[ cfg( target_os = "nto" ) ]
186
187
let flags = 0 ;
187
- // SA_RESTART is supported by qnx https://www.qnx.com/support/knowledgebase.html?id=50130000000SmiD
188
+ // SA_RESTART is supported by qnx https://www.qnx.com/support/knowledgebase.html?id=50130000000SmiD
188
189
#[ cfg( not( target_os = "nto" ) ) ]
189
190
let flags = libc:: SA_RESTART ;
190
191
#[ allow( unused_assignments) ]
@@ -296,23 +297,30 @@ struct GlobalData {
296
297
race_fallback : HalfLock < Option < Prev > > ,
297
298
}
298
299
299
- static mut GLOBAL_DATA : Option < GlobalData > = None ;
300
+ static GLOBAL_DATA : AtomicPtr < GlobalData > = AtomicPtr :: new ( ptr :: null_mut ( ) ) ;
300
301
#[ allow( deprecated) ]
301
302
static GLOBAL_INIT : Once = ONCE_INIT ;
302
303
303
304
impl GlobalData {
304
305
fn get ( ) -> & ' static Self {
305
- unsafe { GLOBAL_DATA . as_ref ( ) . unwrap ( ) }
306
+ let data = GLOBAL_DATA . load ( Ordering :: Acquire ) ;
307
+ // # Safety
308
+ //
309
+ // * The data actually does live forever - created by Box::into_raw.
310
+ // * It is _never_ modified (apart for interior mutability, but that one is fine).
311
+ unsafe { data. as_ref ( ) . expect ( "We shall be set up already" ) }
306
312
}
307
313
fn ensure ( ) -> & ' static Self {
308
- GLOBAL_INIT . call_once ( || unsafe {
309
- GLOBAL_DATA = Some ( GlobalData {
314
+ GLOBAL_INIT . call_once ( || {
315
+ let data = Box :: into_raw ( Box :: new ( GlobalData {
310
316
data : HalfLock :: new ( SignalData {
311
317
signals : HashMap :: new ( ) ,
312
318
next_id : 1 ,
313
319
} ) ,
314
320
race_fallback : HalfLock :: new ( None ) ,
315
- } ) ;
321
+ } ) ) ;
322
+ let old = GLOBAL_DATA . swap ( data, Ordering :: Release ) ;
323
+ assert ! ( old. is_null( ) ) ;
316
324
} ) ;
317
325
Self :: get ( )
318
326
}
0 commit comments