[2020-02] [merp] Add API methods for getting hashcode/reason of last crash (#19978)
[mono-project.git] / mcs / class / corlib / Mono / Runtime.cs
blobc85a3a3b1f556d9ae4d6225992d1d9abcd0bff16
1 //
2 // Mono Runtime gateway functions
3 //
4 //
6 //
7 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System;
30 using System.IO;
31 using System.Runtime.CompilerServices;
32 using System.Runtime.InteropServices;
34 namespace Mono {
36 #if MOBILE || XAMMAC_4_5
37 public
38 #endif
39 static class Runtime
42 [MethodImplAttribute (MethodImplOptions.InternalCall)]
43 private static extern void mono_runtime_install_handlers ();
45 #if MOBILE || XAMMAC_4_5
46 public
47 #else
48 internal
49 #endif
50 static void InstallSignalHandlers ()
52 mono_runtime_install_handlers ();
55 #if MOBILE || XAMMAC_4_5
56 [MethodImplAttribute (MethodImplOptions.InternalCall)]
57 static extern void mono_runtime_cleanup_handlers ();
59 public static void RemoveSignalHandlers ()
61 mono_runtime_cleanup_handlers ();
63 #endif
65 // Should not be removed intended for external use
66 // Safe to be called using reflection
67 // Format is undefined only for use as a string for reporting
68 [MethodImplAttribute (MethodImplOptions.InternalCall)]
69 #if MOBILE || XAMMAC_4_5
70 public
71 #else
72 internal
73 #endif
74 static extern string GetDisplayName ();
76 [MethodImplAttribute (MethodImplOptions.InternalCall)]
77 static extern string GetNativeStackTrace (Exception exception);
79 public static bool SetGCAllowSynchronousMajor (bool flag)
81 // No longer used
82 return true;
85 static object exception_capture = new object ();
87 [MethodImplAttribute (MethodImplOptions.InternalCall)]
88 static extern string ExceptionToState_internal (Exception exc, out ulong portable_hash, out ulong unportable_hash);
90 static Tuple<String, ulong, ulong>
91 ExceptionToState (Exception exc)
93 ulong portable_hash;
94 ulong unportable_hash;
95 string payload_str = ExceptionToState_internal (exc, out portable_hash, out unportable_hash);
97 return new Tuple<String, ulong, ulong> (payload_str, portable_hash, unportable_hash);
101 #if !MOBILE
102 [MethodImplAttribute (MethodImplOptions.InternalCall)]
103 static extern void DisableMicrosoftTelemetry ();
105 [MethodImplAttribute (MethodImplOptions.InternalCall)]
106 static extern void EnableMicrosoftTelemetry_internal (IntPtr appBundleID, IntPtr appSignature, IntPtr appVersion, IntPtr merpGUIPath, IntPtr appPath, IntPtr configDir);
108 [MethodImplAttribute (MethodImplOptions.InternalCall)]
109 static extern void SendMicrosoftTelemetry_internal (IntPtr payload, ulong portable_hash, ulong unportable_hash);
111 [MethodImplAttribute (MethodImplOptions.InternalCall)]
112 static extern void WriteStateToFile_internal (IntPtr payload, ulong portable_hash, ulong unportable_hash);
114 static void
115 WriteStateToFile (Exception exc)
117 ulong portable_hash;
118 ulong unportable_hash;
119 string payload_str = ExceptionToState_internal (exc, out portable_hash, out unportable_hash);
120 using (var payload_chars = RuntimeMarshal.MarshalString (payload_str))
122 WriteStateToFile_internal (payload_chars.Value, portable_hash, unportable_hash);
126 static void SendMicrosoftTelemetry (string payload_str, ulong portable_hash, ulong unportable_hash)
128 if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) {
129 using (var payload_chars = RuntimeMarshal.MarshalString (payload_str))
131 SendMicrosoftTelemetry_internal (payload_chars.Value, portable_hash, unportable_hash);
133 } else {
134 throw new PlatformNotSupportedException("Merp support is currently only supported on OSX.");
138 // Usage:
140 // catch (Exception exc) {
141 // var monoType = Type.GetType ("Mono.Runtime", false);
142 // var m = monoType.GetMethod("SendExceptionToTelemetry", BindingFlags.NonPublic | BindingFlags.Static);
143 // m.Invoke(null, new object[] { exc });
144 // }
145 static void SendExceptionToTelemetry (Exception exc)
147 ulong portable_hash;
148 ulong unportable_hash;
149 lock (exception_capture)
151 string payload_str = ExceptionToState_internal (exc, out portable_hash, out unportable_hash);
152 SendMicrosoftTelemetry (payload_str, portable_hash, unportable_hash);
156 // All must be set except for configDir_str
157 static void EnableMicrosoftTelemetry (string appBundleID_str, string appSignature_str, string appVersion_str, string merpGUIPath_str, string unused /* eventType_str */, string appPath_str, string configDir_str)
159 if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) {
160 using (var appBundleID_chars = RuntimeMarshal.MarshalString (appBundleID_str))
161 using (var appSignature_chars = RuntimeMarshal.MarshalString (appSignature_str))
162 using (var appVersion_chars = RuntimeMarshal.MarshalString (appVersion_str))
163 using (var merpGUIPath_chars = RuntimeMarshal.MarshalString (merpGUIPath_str))
164 using (var appPath_chars = RuntimeMarshal.MarshalString (appPath_str))
165 using (var configDir_chars = RuntimeMarshal.MarshalString (configDir_str))
167 EnableMicrosoftTelemetry_internal (appBundleID_chars.Value, appSignature_chars.Value, appVersion_chars.Value, merpGUIPath_chars.Value, appPath_chars.Value, configDir_chars.Value);
169 } else {
170 throw new PlatformNotSupportedException("Merp support is currently only supported on OSX.");
173 #endif
175 [MethodImplAttribute (MethodImplOptions.InternalCall)]
176 static extern string DumpStateSingle_internal (out ulong portable_hash, out ulong unportable_hash);
178 [MethodImplAttribute (MethodImplOptions.InternalCall)]
179 static extern string DumpStateTotal_internal (out ulong portable_hash, out ulong unportable_hash);
181 static Tuple<String, ulong, ulong>
182 DumpStateSingle ()
184 ulong portable_hash;
185 ulong unportable_hash;
186 string payload_str = DumpStateSingle_internal (out portable_hash, out unportable_hash);
188 return new Tuple<String, ulong, ulong> (payload_str, portable_hash, unportable_hash);
191 static Tuple<String, ulong, ulong>
192 DumpStateTotal ()
194 ulong portable_hash;
195 ulong unportable_hash;
196 string payload_str = DumpStateTotal_internal (out portable_hash, out unportable_hash);
198 return new Tuple<String, ulong, ulong> (payload_str, portable_hash, unportable_hash);
201 [MethodImplAttribute (MethodImplOptions.InternalCall)]
202 static extern void RegisterReportingForAllNativeLibs_internal ();
204 static void RegisterReportingForAllNativeLibs ()
206 RegisterReportingForAllNativeLibs_internal ();
209 [MethodImplAttribute (MethodImplOptions.InternalCall)]
210 static extern void RegisterReportingForNativeLib_internal (IntPtr modulePathSuffix, IntPtr moduleName);
212 static void RegisterReportingForNativeLib (string modulePathSuffix_str, string moduleName_str)
214 using (var modulePathSuffix_chars = RuntimeMarshal.MarshalString (modulePathSuffix_str))
215 using (var moduleName_chars = RuntimeMarshal.MarshalString (moduleName_str))
217 RegisterReportingForNativeLib_internal (modulePathSuffix_chars.Value, moduleName_chars.Value);
221 [MethodImplAttribute (MethodImplOptions.InternalCall)]
222 static extern void EnableCrashReportLog_internal (IntPtr directory);
224 static void EnableCrashReportLog (string directory_str)
226 using (var directory_chars = RuntimeMarshal.MarshalString (directory_str))
228 EnableCrashReportLog_internal (directory_chars.Value);
232 enum CrashReportLogLevel : int {
233 MonoSummaryNone = 0,
234 MonoSummarySetup,
235 MonoSummarySuspendHandshake,
236 MonoSummaryUnmanagedStacks,
237 MonoSummaryManagedStacks,
238 MonoSummaryStateWriter,
239 MonoSummaryStateWriterDone,
240 MonoSummaryMerpWriter,
241 MonoSummaryMerpInvoke,
242 MonoSummaryCleanup,
243 MonoSummaryDone,
245 MonoSummaryDoubleFault
248 [MethodImplAttribute (MethodImplOptions.InternalCall)]
249 static extern int CheckCrashReportLog_internal (IntPtr directory, bool clear);
251 static CrashReportLogLevel CheckCrashReportLog (string directory_str, bool clear)
253 using (var directory_chars = RuntimeMarshal.MarshalString (directory_str))
255 return (CrashReportLogLevel) CheckCrashReportLog_internal (directory_chars.Value, clear);
259 static string get_breadcrumb_value (string file_prefix, string directory_str, bool clear)
261 var allfiles = Directory.GetFiles (directory_str, $"{file_prefix}_*" );
262 if (allfiles.Length == 0)
263 return string.Empty;
265 if (allfiles.Length > 1) {
266 // it's impossible to tell which breadcrumb is the last one (let's not trust filesystem timestamps)
267 // delete the multiple files so at least next crash can make sense
268 try {
269 Array.ForEach (allfiles, f => File.Delete (f) );
270 } catch (Exception) { }
272 return string.Empty;
275 if (clear)
276 File.Delete (allfiles [0]);
278 var filename = Path.GetFileName (allfiles [0]);
279 return filename.Substring (file_prefix.Length + 1);
282 static long CheckCrashReportHash (string directory_str, bool clear)
284 var value = get_breadcrumb_value ("crash_hash", directory_str, clear);
285 if (value == string.Empty)
286 return 0;
287 else
288 return Convert.ToInt64 (value, 16);
291 static string CheckCrashReportReason (string directory_str, bool clear)
293 return get_breadcrumb_value ("crash_reason", directory_str, clear);
296 [MethodImplAttribute (MethodImplOptions.InternalCall)]
297 static extern void AnnotateMicrosoftTelemetry_internal (IntPtr key, IntPtr val);
299 static void AnnotateMicrosoftTelemetry (string key, string val)
301 using (var key_chars = RuntimeMarshal.MarshalString (key))
302 using (var val_chars = RuntimeMarshal.MarshalString (val))
304 AnnotateMicrosoftTelemetry_internal (key_chars.Value, val_chars.Value);