@@ -178,29 +178,18 @@ mod lock {
178
178
}
179
179
180
180
#[ cfg( all( windows, feature = "dbghelp" ) ) ]
181
- struct Cleanup {
182
- handle : winapi:: um:: winnt:: HANDLE ,
183
- opts : winapi:: shared:: minwindef:: DWORD ,
184
- }
181
+ mod dbghelp {
182
+ use core:: marker:: PhantomData ;
183
+ use winapi:: um:: dbghelp:: { SymInitializeW , SymCleanup } ;
185
184
186
- #[ cfg( all( windows, feature = "dbghelp" ) ) ]
187
- enum Trace {
188
- Inside ( Option < Cleanup > ) ,
189
- Outside ,
190
- }
191
-
192
- thread_local ! {
193
- #[ cfg( all( windows, feature = "dbghelp" ) ) ]
194
- static TRACE_CLEANUP : std:: cell:: RefCell <Trace > = std:: cell:: RefCell :: new( Trace :: Outside ) ;
195
- }
185
+ // Not sure why these are missing in winapi
196
186
197
- #[ cfg( all( windows, feature = "dbghelp" ) ) ]
198
- unsafe fn dbghelp_init ( ) -> Option < Cleanup > {
199
- use winapi:: shared:: minwindef;
200
- use winapi:: um:: { dbghelp, processthreadsapi} ;
187
+ const SYMOPT_DEFERRED_LOADS : winapi:: shared:: minwindef:: DWORD = 0x00000004 ;
201
188
202
- use std:: sync:: { Mutex , Once , ONCE_INIT } ;
203
- use std:: boxed:: Box ;
189
+ extern "system" {
190
+ fn SymGetOptions ( ) -> winapi:: shared:: minwindef:: DWORD ;
191
+ fn SymSetOptions ( options : winapi:: shared:: minwindef:: DWORD ) ;
192
+ }
204
193
205
194
// Initializing symbols has significant overhead, but initializing only once
206
195
// without cleanup causes problems for external sources. For example, the
@@ -212,68 +201,84 @@ unsafe fn dbghelp_init() -> Option<Cleanup> {
212
201
// As a compromise, we'll keep track of the number of internal initialization
213
202
// requests within a single API call in order to minimize the number of
214
203
// init/cleanup cycles.
215
- static mut REF_COUNT : * mut Mutex < usize > = 0 as * mut _ ;
216
- static mut INIT : Once = ONCE_INIT ;
204
+ static mut DBGHELP : DbgHelp = DbgHelp {
205
+ ref_count : 0 ,
206
+ opts : 0 ,
207
+ handle : core:: ptr:: null_mut ( )
208
+ } ;
209
+
210
+ struct DbgHelp {
211
+ ref_count : usize ,
212
+ handle : winapi:: um:: winnt:: HANDLE ,
213
+ opts : winapi:: shared:: minwindef:: DWORD ,
214
+ }
217
215
218
- INIT . call_once ( || {
219
- REF_COUNT = Box :: into_raw ( Box :: new ( Mutex :: new ( 0 ) ) ) ;
220
- } ) ;
216
+ pub struct Cleanup ( PhantomData < * mut ( ) > ) ;
221
217
222
- // Not sure why these are missing in winapi
223
- const SYMOPT_DEFERRED_LOADS : minwindef:: DWORD = 0x00000004 ;
224
- extern "system" {
225
- fn SymGetOptions ( ) -> minwindef:: DWORD ;
226
- fn SymSetOptions ( options : minwindef:: DWORD ) ;
218
+ impl Clone for Cleanup {
219
+ fn clone ( & self ) -> Cleanup {
220
+ unsafe {
221
+ DBGHELP . ref_count += 1 ;
222
+ }
223
+ Cleanup ( PhantomData )
224
+ }
227
225
}
228
226
229
227
impl Drop for Cleanup {
230
228
fn drop ( & mut self ) {
231
229
unsafe {
232
- let mut ref_count_guard = ( & * REF_COUNT ) . lock ( ) . unwrap ( ) ;
233
- * ref_count_guard -= 1 ;
234
-
235
- if * ref_count_guard == 0 {
236
- dbghelp:: SymCleanup ( self . handle ) ;
237
- SymSetOptions ( self . opts ) ;
230
+ DBGHELP . ref_count -= 1 ;
231
+ if DBGHELP . ref_count == 0 {
232
+ SymCleanup ( DBGHELP . handle ) ;
233
+ SymSetOptions ( DBGHELP . opts ) ;
238
234
}
239
235
}
240
236
}
241
237
}
242
238
243
- impl Clone for Cleanup {
244
- fn clone ( & self ) -> Cleanup {
245
- unsafe {
246
- let mut ref_count_guard = ( & * REF_COUNT ) . lock ( ) . unwrap ( ) ;
247
- * ref_count_guard += 1 ;
248
- }
249
- Cleanup {
250
- opts : self . opts ,
251
- handle : self . handle
252
- }
253
- }
239
+ /// Tracks whether or not we have initialized dbghelp.dll inside of a call to `trace`.
240
+ pub enum Trace {
241
+ Inside ( Option < Cleanup > ) ,
242
+ Outside ,
254
243
}
255
244
256
- let opts = SymGetOptions ( ) ;
257
- let handle = processthreadsapi:: GetCurrentProcess ( ) ;
245
+ thread_local ! {
246
+ pub static TRACE_CLEANUP : core:: cell:: RefCell <Trace > = core:: cell:: RefCell :: new( Trace :: Outside ) ;
247
+ }
258
248
259
- let mut ref_count_guard = ( & * REF_COUNT ) . lock ( ) . unwrap ( ) ;
249
+ /// Requires external synchronization
250
+ pub unsafe fn init ( ) -> Option < Cleanup > {
251
+ use winapi:: shared:: minwindef:: TRUE ;
252
+ use winapi:: um:: processthreadsapi:: GetCurrentProcess ;
260
253
261
- if * ref_count_guard > 0 {
262
- * ref_count_guard += 1 ;
263
- return Some ( Cleanup { handle, opts } ) ;
264
- }
254
+ if DBGHELP . ref_count > 0 {
255
+ DBGHELP . ref_count += 1 ;
256
+ return Some ( Cleanup ( core:: marker:: PhantomData ) ) ;
257
+ }
258
+
259
+ let opts = SymGetOptions ( ) ;
260
+ let handle = GetCurrentProcess ( ) ;
265
261
266
- SymSetOptions ( opts | SYMOPT_DEFERRED_LOADS ) ;
262
+ SymSetOptions ( opts | SYMOPT_DEFERRED_LOADS ) ;
267
263
268
- let ret = dbghelp:: SymInitializeW ( handle,
269
- 0 as * mut _ ,
270
- minwindef:: TRUE ) ;
264
+ let ret = SymInitializeW ( handle, 0 as * mut _ , TRUE ) ;
265
+ if ret != TRUE {
266
+ // Revert our changes
267
+ SymSetOptions ( opts) ;
271
268
272
- if ret != minwindef:: TRUE {
273
- // Symbols may have been initialized by another library or an external debugger
274
- None
275
- } else {
276
- * ref_count_guard += 1 ;
277
- Some ( Cleanup { handle, opts } )
269
+ // Symbols may have been initialized by another library or an external debugger
270
+ None
271
+ } else {
272
+ DBGHELP . ref_count += 1 ;
273
+ DBGHELP . handle = handle;
274
+ DBGHELP . opts = opts;
275
+ Some ( Cleanup ( PhantomData ) )
276
+ }
278
277
}
279
- }
278
+ }
279
+
280
+ #[ cfg( all( windows, feature = "dbghelp" ) ) ]
281
+ use dbghelp:: init as dbghelp_init;
282
+
283
+ #[ cfg( all( windows, feature = "dbghelp" ) ) ]
284
+ use dbghelp:: { Trace , TRACE_CLEANUP } ;
0 commit comments