@@ -7,10 +7,9 @@ namespace ICSharpCode.CodeConverter.Shared
77{
88 internal static class RoslynCrashPreventer
99 {
10- private static readonly object _exchangeLock = new object ( ) ;
10+ private static readonly DelegatingHandler _codeAnalysisHandler = new DelegatingHandler ( typeof ( Compilation ) . Assembly , "Microsoft.CodeAnalysis.FatalError" ) ;
11+ private static readonly DelegatingHandler _errorReportingHandler = new DelegatingHandler ( typeof ( WorkspaceDiagnostic ) . Assembly , "Microsoft.CodeAnalysis.ErrorReporting.FatalError" ) ;
1112 private static volatile int _currentUses ;
12- private static Action < Exception > _codeAnalysisErrorHandler ;
13- private static Action < Exception > _errorReportingErrorHandler ;
1413
1514 /// <summary>
1615 /// Use this to stop the library exiting the process without telling us.
@@ -23,55 +22,59 @@ internal static class RoslynCrashPreventer
2322 /// See https://github.com/icsharpcode/CodeConverter/issues/521 and https://github.com/icsharpcode/CodeConverter/issues/484
2423 /// There are other ways to find these bugs - just run the expander/reducer on a couple of whole open source projects and the bugs will pile up.
2524 /// </remarks>
26- public static IDisposable Create ( Action < Exception > logError )
25+ public static IDisposable Create ( Action < Exception > logErrorToUseIfNotSet )
2726 {
28- var codeAnalysisAssembly = ( typeof ( Compilation ) . Assembly , "Microsoft.CodeAnalysis.FatalError" ) ;
29- var errorReportingAssembly = ( typeof ( WorkspaceDiagnostic ) . Assembly , "Microsoft.CodeAnalysis.ErrorReporting.FatalError" ) ;
30-
31- TryExchangeHandler ( WrappedCodeAnalysisErrorHandler ( logError ) , codeAnalysisAssembly , ref _codeAnalysisErrorHandler ) ;
32- TryExchangeHandler ( WrappedErrorReportingHandler ( logError ) , errorReportingAssembly , ref _errorReportingErrorHandler ) ;
33-
27+ _codeAnalysisHandler . TryExchangeHandler ( logErrorToUseIfNotSet ) ;
28+ _errorReportingHandler . TryExchangeHandler ( logErrorToUseIfNotSet ) ;
3429 Interlocked . Increment ( ref _currentUses ) ;
3530 return new ActionDisposable ( ( ) => Interlocked . Decrement ( ref _currentUses ) ) ;
3631 }
3732
38- private static void TryExchangeHandler ( Action < Exception > logError , ( Assembly Assembly , string ) handlerContainer , ref Action < Exception > originalHandler )
33+ private class DelegatingHandler
3934 {
40- if ( originalHandler != null || logError == null ) return ;
41- lock ( _exchangeLock ) {
42- originalHandler ??= ExchangeFatalErrorHandler ( logError , handlerContainer ) ;
35+ private readonly Assembly _assembly ;
36+ private readonly string _containingType ;
37+ private readonly object _exchangeLock = new object ( ) ;
38+ private Action < Exception > _originalHandler ;
39+
40+ public DelegatingHandler ( Assembly assembly , string containingType )
41+ {
42+ _assembly = assembly ;
43+ _containingType = containingType ;
4344 }
44- }
4545
46- private static Action < Exception > ExchangeFatalErrorHandler ( Action < Exception > errorHandler , ( Assembly assembly , string containingType ) container )
47- {
48- try {
49- var fataErrorType = container . assembly . GetType ( container . containingType ) ;
50- var fatalHandlerField = fataErrorType . GetField ( "s_fatalHandler" , BindingFlags . NonPublic | BindingFlags . Static ) ;
51- var originalHandler = ( Action < Exception > ) fatalHandlerField . GetValue ( null ) ;
52- if ( originalHandler != null ) {
53- fatalHandlerField . SetValue ( null , errorHandler ) ;
46+ public void TryExchangeHandler ( Action < Exception > logError )
47+ {
48+ if ( _originalHandler != null || logError == null ) return ;
49+ lock ( _exchangeLock ) {
50+ _originalHandler ??= ExchangeFatalErrorHandler ( WrappedCodeAnalysisErrorHandler ( logError ) ) ;
5451 }
55- return originalHandler ;
56- } catch ( Exception ) {
57- return null ;
5852 }
59- }
6053
61- private static Action < Exception > WrappedCodeAnalysisErrorHandler ( Action < Exception > errorHandler ) => e => {
62- if ( _currentUses > 0 ) {
63- errorHandler ( e ) ;
64- } else {
65- _codeAnalysisErrorHandler ( e ) ;
66- }
67- } ;
54+ private Action < Exception > ExchangeFatalErrorHandler ( Action < Exception > errorHandler )
55+ {
56+ try {
57+ var fataErrorType = _assembly . GetType ( _containingType ) ;
58+ var fatalHandlerField =
59+ fataErrorType . GetField ( "s_fatalHandler" , BindingFlags . NonPublic | BindingFlags . Static ) ;
60+ var originalHandler = ( Action < Exception > ) fatalHandlerField . GetValue ( null ) ;
61+ if ( originalHandler != null ) {
62+ fatalHandlerField . SetValue ( null , errorHandler ) ;
63+ }
6864
69- private static Action < Exception > WrappedErrorReportingHandler ( Action < Exception > errorHandler ) => e => {
70- if ( _currentUses > 0 ) {
71- errorHandler ( e ) ;
72- } else {
73- _errorReportingErrorHandler ( e ) ;
65+ return originalHandler ;
66+ } catch ( Exception ) {
67+ return null ;
68+ }
7469 }
75- } ;
70+
71+ private Action < Exception > WrappedCodeAnalysisErrorHandler ( Action < Exception > errorHandler ) => e => {
72+ if ( _currentUses > 0 ) {
73+ errorHandler ( e ) ;
74+ } else {
75+ _originalHandler ( e ) ;
76+ }
77+ } ;
78+ }
7679 }
7780}
0 commit comments