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