@@ -21,7 +21,7 @@ namespace System.Diagnostics
21
21
// Modifying the order or fields of this object may require other changes
22
22
// to the unmanaged definition of the StackFrameHelper class, in
23
23
// VM\DebugDebugger.h. The binder will catch some of these layout problems.
24
- internal class StackFrameHelper : IDisposable
24
+ internal class StackFrameHelper
25
25
{
26
26
private Thread targetThread ;
27
27
private int [ ] rgiOffset ;
@@ -44,16 +44,14 @@ internal class StackFrameHelper : IDisposable
44
44
private int [ ] rgiLineNumber ;
45
45
private int [ ] rgiColumnNumber ;
46
46
private bool [ ] rgiLastFrameFromForeignExceptionStackTrace ;
47
- private GetSourceLineInfoDelegate getSourceLineInfo ;
48
47
private int iFrameCount ;
49
48
#pragma warning restore 414
50
49
51
50
private delegate void GetSourceLineInfoDelegate ( string assemblyPath , IntPtr loadedPeAddress , int loadedPeSize ,
52
51
IntPtr inMemoryPdbAddress , int inMemoryPdbSize , int methodToken , int ilOffset ,
53
52
out string sourceFile , out int sourceLine , out int sourceColumn ) ;
54
53
55
- private static Type s_symbolsType = null ;
56
- private static MethodInfo s_symbolsMethodInfo = null ;
54
+ private static GetSourceLineInfoDelegate s_getSourceLineInfo = null ;
57
55
58
56
[ ThreadStatic ]
59
57
private static int t_reentrancy = 0 ;
@@ -74,7 +72,6 @@ public StackFrameHelper(Thread target)
74
72
rgFilename = null ;
75
73
rgiLineNumber = null ;
76
74
rgiColumnNumber = null ;
77
- getSourceLineInfo = null ;
78
75
79
76
rgiLastFrameFromForeignExceptionStackTrace = null ;
80
77
@@ -107,27 +104,32 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce
107
104
t_reentrancy ++ ;
108
105
try
109
106
{
110
- if ( s_symbolsMethodInfo == null )
107
+ if ( s_getSourceLineInfo == null )
111
108
{
112
- s_symbolsType = Type . GetType (
109
+ Type symbolsType = Type . GetType (
113
110
"System.Diagnostics.StackTraceSymbols, System.Diagnostics.StackTrace, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ,
114
111
throwOnError : false ) ;
115
112
116
- if ( s_symbolsType == null )
113
+ if ( symbolsType == null )
114
+ {
117
115
return ;
116
+ }
118
117
119
- s_symbolsMethodInfo = s_symbolsType . GetMethod ( "GetSourceLineInfo" , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance ) ;
120
- if ( s_symbolsMethodInfo == null )
118
+ MethodInfo symbolsMethodInfo = symbolsType . GetMethod ( "GetSourceLineInfo" , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance ) ;
119
+ if ( symbolsMethodInfo == null )
120
+ {
121
121
return ;
122
- }
122
+ }
123
123
124
- if ( getSourceLineInfo == null )
125
- {
126
124
// Create an instance of System.Diagnostics.Stacktrace.Symbols
127
- object target = Activator . CreateInstance ( s_symbolsType ) ;
125
+ object target = Activator . CreateInstance ( symbolsType ) ;
128
126
129
127
// Create an instance delegate for the GetSourceLineInfo method
130
- getSourceLineInfo = ( GetSourceLineInfoDelegate ) s_symbolsMethodInfo . CreateDelegate ( typeof ( GetSourceLineInfoDelegate ) , target ) ;
128
+ GetSourceLineInfoDelegate getSourceLineInfo = ( GetSourceLineInfoDelegate ) symbolsMethodInfo . CreateDelegate ( typeof ( GetSourceLineInfoDelegate ) , target ) ;
129
+
130
+ // We could race with another thread. It doesn't matter if we win or lose, the losing instance will be GC'ed and all threads including this one will
131
+ // use the winning instance
132
+ Interlocked . CompareExchange ( ref s_getSourceLineInfo , getSourceLineInfo , null ) ;
131
133
}
132
134
133
135
for ( int index = 0 ; index < iFrameCount ; index ++ )
@@ -136,7 +138,7 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce
136
138
// ENC or the source/line info was already retrieved, the method token is 0.
137
139
if ( rgiMethodToken [ index ] != 0 )
138
140
{
139
- getSourceLineInfo ( rgAssemblyPath [ index ] , rgLoadedPeAddress [ index ] , rgiLoadedPeSize [ index ] ,
141
+ s_getSourceLineInfo ( rgAssemblyPath [ index ] , rgLoadedPeAddress [ index ] , rgiLoadedPeSize [ index ] ,
140
142
rgInMemoryPdbAddress [ index ] , rgiInMemoryPdbSize [ index ] , rgiMethodToken [ index ] ,
141
143
rgiILOffset [ index ] , out rgFilename [ index ] , out rgiLineNumber [ index ] , out rgiColumnNumber [ index ] ) ;
142
144
}
@@ -151,18 +153,6 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce
151
153
}
152
154
}
153
155
154
- void IDisposable . Dispose ( )
155
- {
156
- if ( getSourceLineInfo != null )
157
- {
158
- IDisposable disposable = getSourceLineInfo . Target as IDisposable ;
159
- if ( disposable != null )
160
- {
161
- disposable . Dispose ( ) ;
162
- }
163
- }
164
- }
165
-
166
156
public virtual MethodBase GetMethodBase ( int i )
167
157
{
168
158
// There may be a better way to do this.
@@ -362,56 +352,57 @@ private void CaptureStackTrace(int iSkip, bool fNeedFileInfo, Thread targetThrea
362
352
{
363
353
m_iMethodsToSkip += iSkip ;
364
354
365
- using ( StackFrameHelper StackF = new StackFrameHelper ( targetThread ) )
366
- {
367
- StackF . InitializeSourceInfo ( 0 , fNeedFileInfo , e ) ;
368
-
369
- m_iNumOfFrames = StackF . GetNumberOfFrames ( ) ;
355
+ StackFrameHelper StackF = new StackFrameHelper ( targetThread ) ;
356
+
357
+ StackF . InitializeSourceInfo ( 0 , fNeedFileInfo , e ) ;
370
358
371
- if ( m_iMethodsToSkip > m_iNumOfFrames )
372
- m_iMethodsToSkip = m_iNumOfFrames ;
359
+ m_iNumOfFrames = StackF . GetNumberOfFrames ( ) ;
373
360
374
- if ( m_iNumOfFrames != 0 )
375
- {
376
- frames = new StackFrame [ m_iNumOfFrames ] ;
361
+ if ( m_iMethodsToSkip > m_iNumOfFrames )
362
+ m_iMethodsToSkip = m_iNumOfFrames ;
377
363
378
- for ( int i = 0 ; i < m_iNumOfFrames ; i ++ )
379
- {
380
- bool fDummy1 = true ;
381
- bool fDummy2 = true ;
382
- StackFrame sfTemp = new StackFrame ( fDummy1 , fDummy2 ) ;
364
+ if ( m_iNumOfFrames != 0 )
365
+ {
366
+ frames = new StackFrame [ m_iNumOfFrames ] ;
383
367
384
- sfTemp . SetMethodBase ( StackF . GetMethodBase ( i ) ) ;
385
- sfTemp . SetOffset ( StackF . GetOffset ( i ) ) ;
386
- sfTemp . SetILOffset ( StackF . GetILOffset ( i ) ) ;
368
+ for ( int i = 0 ; i < m_iNumOfFrames ; i ++ )
369
+ {
370
+ bool fDummy1 = true ;
371
+ bool fDummy2 = true ;
372
+ StackFrame sfTemp = new StackFrame ( fDummy1 , fDummy2 ) ;
387
373
388
- sfTemp . SetIsLastFrameFromForeignExceptionStackTrace ( StackF . IsLastFrameFromForeignExceptionStackTrace ( i ) ) ;
374
+ sfTemp . SetMethodBase ( StackF . GetMethodBase ( i ) ) ;
375
+ sfTemp . SetOffset ( StackF . GetOffset ( i ) ) ;
376
+ sfTemp . SetILOffset ( StackF . GetILOffset ( i ) ) ;
389
377
390
- if ( fNeedFileInfo )
391
- {
392
- sfTemp . SetFileName ( StackF . GetFilename ( i ) ) ;
393
- sfTemp . SetLineNumber ( StackF . GetLineNumber ( i ) ) ;
394
- sfTemp . SetColumnNumber ( StackF . GetColumnNumber ( i ) ) ;
395
- }
378
+ sfTemp . SetIsLastFrameFromForeignExceptionStackTrace ( StackF . IsLastFrameFromForeignExceptionStackTrace ( i ) ) ;
396
379
397
- frames [ i ] = sfTemp ;
380
+ if ( fNeedFileInfo )
381
+ {
382
+ sfTemp . SetFileName ( StackF . GetFilename ( i ) ) ;
383
+ sfTemp . SetLineNumber ( StackF . GetLineNumber ( i ) ) ;
384
+ sfTemp . SetColumnNumber ( StackF . GetColumnNumber ( i ) ) ;
398
385
}
399
386
400
- // CalculateFramesToSkip skips all frames in the System.Diagnostics namespace,
401
- // but this is not desired if building a stack trace from an exception.
402
- if ( e == null )
403
- m_iMethodsToSkip += CalculateFramesToSkip ( StackF , m_iNumOfFrames ) ;
387
+ frames [ i ] = sfTemp ;
388
+ }
404
389
405
- m_iNumOfFrames -= m_iMethodsToSkip ;
406
- if ( m_iNumOfFrames < 0 )
407
- {
408
- m_iNumOfFrames = 0 ;
409
- }
390
+ // CalculateFramesToSkip skips all frames in the System.Diagnostics namespace,
391
+ // but this is not desired if building a stack trace from an exception.
392
+ if ( e == null )
393
+ m_iMethodsToSkip += CalculateFramesToSkip ( StackF , m_iNumOfFrames ) ;
394
+
395
+ m_iNumOfFrames -= m_iMethodsToSkip ;
396
+ if ( m_iNumOfFrames < 0 )
397
+ {
398
+ m_iNumOfFrames = 0 ;
410
399
}
400
+ }
411
401
412
- // In case this is the same object being re-used, set frames to null
413
- else
414
- frames = null ;
402
+ // In case this is the same object being re-used, set frames to null
403
+ else
404
+ {
405
+ frames = null ;
415
406
}
416
407
}
417
408
0 commit comments