Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -192,23 +192,49 @@ public struct ExceptionInformationArray
}

private static ulong s_crashingThreadId;
private static IntPtr s_triageBufferAddress;
private static int s_triageBufferSize;
private static volatile int s_crashInfoPresent;

internal static void SerializeCrashInfo(RhFailFastReason reason, string? message, Exception? exception)
{
int previousState = Interlocked.CompareExchange(ref s_crashInfoPresent, -1, 0);
if (previousState == 0)
{
CrashInfo crashInfo = new();

crashInfo.Open(reason, Thread.CurrentOSThreadId, message ?? GetStringForFailFastReason(reason));
if (exception != null)
{
crashInfo.WriteException(exception);
}
crashInfo.Close();
s_triageBufferAddress = crashInfo.TriageBufferAddress;
s_triageBufferSize = crashInfo.TriageBufferSize;

s_crashInfoPresent = 1;
}
else
{
while (s_crashInfoPresent != 1)
{
// Some other thread is generating the crash info
Thread.Sleep(1);
}
}
}

[DoesNotReturn]
internal static unsafe void FailFast(string? message = null, Exception? exception = null, string? errorSource = null,
RhFailFastReason reason = RhFailFastReason.EnvironmentFailFast,
IntPtr pExAddress = 0, IntPtr pExContext = 0)
{
IntPtr triageBufferAddress = IntPtr.Zero;
int triageBufferSize = 0;
int errorCode = 0;

ulong currentThreadId = Thread.CurrentOSThreadId;
ulong previousThreadId = Interlocked.CompareExchange(ref s_crashingThreadId, currentThreadId, 0);
if (previousThreadId == 0)
{
CrashInfo crashInfo = new();
crashInfo.Open(reason, s_crashingThreadId, message ?? GetStringForFailFastReason(reason));

bool minimalFailFast = (exception == PreallocatedOutOfMemoryException.Instance);
if (!minimalFailFast)
{
Expand Down Expand Up @@ -264,17 +290,9 @@ internal static unsafe void FailFast(string? message = null, Exception? exceptio
reporter.Report();
}
#endif
} // !minimalFailFast

if (exception != null)
{
crashInfo.WriteException(exception);
}
}

crashInfo.Close();

triageBufferAddress = crashInfo.TriageBufferAddress;
triageBufferSize = crashInfo.TriageBufferSize;
SerializeCrashInfo(reason, message, minimalFailFast ? null : exception);

// Try to map the failure into a HRESULT that makes sense
errorCode = exception != null ? exception.HResult : reason switch
Expand Down Expand Up @@ -310,8 +328,8 @@ internal static unsafe void FailFast(string? message = null, Exception? exceptio
exceptionRecord.NumberParameters = 4;
exceptionRecord.ExceptionInformation[0] = FAST_FAIL_EXCEPTION_DOTNET_AOT;
exceptionRecord.ExceptionInformation[1] = (uint)errorCode;
exceptionRecord.ExceptionInformation[2] = (nuint)triageBufferAddress;
exceptionRecord.ExceptionInformation[3] = (uint)triageBufferSize;
exceptionRecord.ExceptionInformation[2] = (nuint)s_triageBufferAddress;
exceptionRecord.ExceptionInformation[3] = (uint)s_triageBufferSize;

#if TARGET_WINDOWS
Interop.Kernel32.RaiseFailFastException(new IntPtr(&exceptionRecord), pExContext, pExAddress == IntPtr.Zero ? FAIL_FAST_GENERATE_EXCEPTION_ADDRESS : 0);
Expand Down
3 changes: 3 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/AppContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ public static void SetData(string name, object? data)
#endif
internal static void OnUnhandledException(object e)
{
#if NATIVEAOT
RuntimeExceptionHelpers.SerializeCrashInfo(System.Runtime.RhFailFastReason.UnhandledException, (e as Exception)?.Message, e as Exception);
#endif
if (UnhandledException is UnhandledExceptionEventHandler handlers)
{
UnhandledExceptionEventArgs args = new(e, isTerminating: true);
Expand Down
Loading