Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / runtime / exceptionservices / exceptionservicescommon.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*=============================================================================
7 **
8 ** File: ExceptionServicesCommon.cs
9 **
10 **
11 ** Purpose: Contains common usage support entities for advanced exception
12 **          handling/processing scenarios.
13 **
14 ** Created: 11/2/2010
15 ** 
16 ** <owner>Microsoft</owner>
17 ** 
18 =============================================================================*/
19
20 #if FEATURE_EXCEPTIONDISPATCHINFO
21 namespace System.Runtime.ExceptionServices {
22     using System;
23     
24     // This class defines support for seperating the exception dispatch details
25     // (like stack trace, watson buckets, etc) from the actual managed exception
26     // object. This allows us to track error (via the exception object) independent
27     // of the path the error takes.
28     //
29     // This is particularly useful for frameworks like PFX, APM, etc that wish to
30     // propagate exceptions (i.e. errors to be precise) across threads.
31     public sealed class ExceptionDispatchInfo
32     {
33         // Private members that will hold the relevant details.
34         private Exception m_Exception;
35 #if !MONO
36         private string m_remoteStackTrace;
37 #endif
38         private object m_stackTrace;
39 #if !MONO
40         private object m_dynamicMethods;
41         private UIntPtr m_IPForWatsonBuckets;
42         private Object m_WatsonBuckets;
43 #endif
44         
45         private ExceptionDispatchInfo(Exception exception)
46         {
47             // Copy over the details we need to save.
48             m_Exception = exception;
49 #if MONO
50                         var count = exception.captured_traces == null ? 0 : exception.captured_traces.Length;
51                         var stack_traces = new System.Diagnostics.StackTrace [count + 1];
52                         if (count != 0)
53                                 Array.Copy (exception.captured_traces, 0, stack_traces, 0, count);
54
55                         stack_traces [count] = new System.Diagnostics.StackTrace (exception, 0, true);
56                         m_stackTrace = stack_traces;
57 #else
58             m_remoteStackTrace = exception.RemoteStackTrace;
59             
60             // NOTE: don't be tempted to pass the fields for the out params; the containing object
61             //       might be relocated during the call so the pointers will no longer be valid.
62             object stackTrace;
63             object dynamicMethods;
64             m_Exception.GetStackTracesDeepCopy(out stackTrace, out dynamicMethods);
65             m_stackTrace = stackTrace;
66             m_dynamicMethods = dynamicMethods;
67
68             m_IPForWatsonBuckets = exception.IPForWatsonBuckets;
69             m_WatsonBuckets = exception.WatsonBuckets;                                                        
70 #endif
71         }
72
73 #if !MONO
74         internal UIntPtr IPForWatsonBuckets
75         {
76             get
77             {
78                 return m_IPForWatsonBuckets;   
79             }
80         }
81
82         internal object WatsonBuckets
83         {
84             get
85             {
86                 return m_WatsonBuckets;   
87             }
88         }
89 #endif
90         
91         internal object BinaryStackTraceArray
92         {
93             get
94             {
95                 return m_stackTrace;
96             }
97         }
98
99 #if !MONO
100         internal object DynamicMethodArray
101         {
102             get
103             {
104                 return m_dynamicMethods;
105             }
106         }
107
108         internal string RemoteStackTrace
109         {
110             get
111             {
112                 return m_remoteStackTrace;
113             }
114         }
115 #endif
116
117         // This static method is used to create an instance of ExceptionDispatchInfo for
118         // the specified exception object and save all the required details that maybe
119         // needed to be propagated when the exception is "rethrown" on a different thread.
120         public static ExceptionDispatchInfo Capture(Exception source)
121         {
122             if (source == null)
123             {
124                 throw new ArgumentNullException("source", Environment.GetResourceString("ArgumentNull_Obj"));
125             }
126             
127             return new ExceptionDispatchInfo(source);
128         }
129     
130         // Return the exception object represented by this ExceptionDispatchInfo instance
131         public Exception SourceException
132         {
133
134             get
135             {
136                 return m_Exception;   
137             }
138         }
139         
140         // When a framework needs to "Rethrow" an exception on a thread different (but not necessarily so) from
141         // where it was thrown, it should invoke this method against the ExceptionDispatchInfo (EDI)
142         // created for the exception in question.
143         //
144         // This method will restore the original stack trace and bucketing details before throwing
145         // the exception so that it is easy, from debugging standpoint, to understand what really went wrong on
146         // the original thread.
147         public void Throw()
148         {
149             // Restore the exception dispatch details before throwing the exception.
150             m_Exception.RestoreExceptionDispatchInfo(this);
151             throw m_Exception; 
152         }
153     }
154 }
155 #endif // FEATURE_EXCEPTIONDISPATCHINFO