Skip to content

Commit af872f0

Browse files
authored
Report unhandled async exceptions (#117799)
Async exceptions like the ThreadInterruptedException are explicitly prevented from logging unhandled exception details to console. This change removes this special handling and lets them be reported as any other unhandled exception. Close #107594
1 parent c2a1045 commit af872f0

File tree

4 files changed

+21
-24
lines changed

4 files changed

+21
-24
lines changed

src/coreclr/vm/excep.cpp

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3223,21 +3223,6 @@ BOOL IsExceptionOfType(RuntimeExceptionKind reKind, OBJECTREF *pThrowable)
32233223
return CoreLibBinder::IsException(pThrowableMT, reKind);
32243224
}
32253225

3226-
BOOL IsAsyncThreadException(OBJECTREF *pThrowable) {
3227-
STATIC_CONTRACT_NOTHROW;
3228-
STATIC_CONTRACT_GC_NOTRIGGER;
3229-
STATIC_CONTRACT_MODE_COOPERATIVE;
3230-
STATIC_CONTRACT_FORBID_FAULT;
3231-
3232-
if ( (GetThreadNULLOk() && GetThread()->IsRudeAbort() && GetThread()->IsRudeAbortInitiated())
3233-
||IsExceptionOfType(kThreadAbortException, pThrowable)
3234-
||IsExceptionOfType(kThreadInterruptedException, pThrowable)) {
3235-
return TRUE;
3236-
} else {
3237-
return FALSE;
3238-
}
3239-
}
3240-
32413226
BOOL IsUncatchable(OBJECTREF *pThrowable)
32423227
{
32433228
CONTRACTL {
@@ -4960,7 +4945,7 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers,
49604945
IsOutOfMemory)
49614946
{
49624947
// We have to be very careful. If we walk off the end of the stack, the process will just
4963-
// die. e.g. IsAsyncThreadException() and Exception.ToString both consume too much stack -- and can't
4948+
// die. e.g. Exception.ToString both consume too much stack -- and can't
49644949
// be called here.
49654950
dump = FALSE;
49664951

@@ -4973,12 +4958,6 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers,
49734958
PrintToStdErrA("Stack overflow.\n");
49744959
}
49754960
}
4976-
else if (IsAsyncThreadException(&throwable))
4977-
{
4978-
// We don't print anything on async exceptions, like ThreadAbort.
4979-
dump = FALSE;
4980-
INDEBUG(suppressSelectiveBreak=TRUE);
4981-
}
49824961

49834962
// Finally, should we print the message?
49844963
if (dump)

src/coreclr/vm/excep.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ DWORD ComputeEnclosingHandlerNestingLevel(IJitManager *pIJM, const METHODTOKEN&
125125
BOOL IsException(MethodTable *pMT);
126126
BOOL IsExceptionOfType(RuntimeExceptionKind reKind, OBJECTREF *pThrowable);
127127
BOOL IsExceptionOfType(RuntimeExceptionKind reKind, Exception *pException);
128-
BOOL IsAsyncThreadException(OBJECTREF *pThrowable);
129128
BOOL IsUncatchable(OBJECTREF *pThrowable);
130129
VOID FixupOnRethrow(Thread *pCurThread, EXCEPTION_POINTERS *pExceptionPointers);
131130
BOOL UpdateCurrentThrowable(PEXCEPTION_RECORD pExceptionRecord);

src/tests/baseservices/exceptions/unhandled/unhandled.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,15 @@ static void Main(string[] args)
4848
{
4949
throw new Exception("Test");
5050
}
51-
if (args[0] == "mainhardware")
51+
else if (args[0] == "mainhardware")
5252
{
5353
string s = null;
5454
Console.WriteLine(s.Length); // This will cause a NullReferenceException
5555
}
56+
else if (args[0] == "mainthreadinterrupted")
57+
{
58+
throw new ThreadInterruptedException("Test");
59+
}
5660
else if (args[0] == "foreign")
5761
{
5862
InvokeCallbackOnNewThread(&ThrowException);
@@ -79,6 +83,12 @@ static void Main(string[] args)
7983
t.Start();
8084
t.Join();
8185
}
86+
else if (args[0] == "secondarythreadinterrupted")
87+
{
88+
Thread t = new Thread(() => throw new ThreadInterruptedException("Test"));
89+
t.Start();
90+
t.Join();
91+
}
8292
}
8393
}
8494
}

src/tests/baseservices/exceptions/unhandled/unhandledTester.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ static void RunExternalProcess(string unhandledType, string assembly)
109109
throw new Exception("Missing Unhandled exception header");
110110
}
111111
}
112+
if (unhandledType == "mainthreadinterrupted" || unhandledType == "secondarythreadinterrupted")
113+
{
114+
if (lines[0] != "Unhandled exception. System.Threading.ThreadInterruptedException: Test")
115+
{
116+
throw new Exception("Missing Unhandled exception header");
117+
}
118+
}
112119
else if (unhandledType == "foreign")
113120
{
114121
if (!lines[0].StartsWith("Unhandled exception. System.DllNotFoundException:") &&
@@ -149,8 +156,10 @@ public static void TestEntryPoint()
149156
{
150157
RunExternalProcess("main", "unhandled.dll");
151158
RunExternalProcess("mainhardware", "unhandled.dll");
159+
RunExternalProcess("mainthreadinterrupted", "unhandled.dll");
152160
RunExternalProcess("secondary", "unhandled.dll");
153161
RunExternalProcess("secondaryhardware", "unhandled.dll");
162+
RunExternalProcess("secondarythreadinterrupted", "unhandled.dll");
154163
RunExternalProcess("foreign", "unhandled.dll");
155164
File.Delete(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "dependencytodelete.dll"));
156165
RunExternalProcess("missingdependency", "unhandledmissingdependency.dll");

0 commit comments

Comments
 (0)