Skip to content

Commit c08faf9

Browse files
authored
Complete thread abort support for the new EH (#95616)
* Complete thread abort support for the new EH This change adds all the necessary changes to make thread abort work with the new exception handling. * Fix build warning
1 parent a954681 commit c08faf9

File tree

6 files changed

+66
-3
lines changed

6 files changed

+66
-3
lines changed

src/coreclr/vm/excep.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6599,6 +6599,8 @@ void HandleManagedFaultNew(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext
65996599
args[ARGNUM_0] = DWORD_TO_ARGHOLDER(exceptionCode);
66006600
args[ARGNUM_1] = PTR_TO_ARGHOLDER(&exInfo);
66016601

6602+
pThread->IncPreventAbort();
6603+
66026604
//Ex.RhThrowHwEx(exceptionCode, &exInfo)
66036605
CALL_MANAGED_METHOD_NORET(args)
66046606

src/coreclr/vm/exceptionhandling.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5462,6 +5462,8 @@ BOOL HandleHardwareException(PAL_SEHException* ex)
54625462
args[ARGNUM_0] = DWORD_TO_ARGHOLDER(exceptionCode);
54635463
args[ARGNUM_1] = PTR_TO_ARGHOLDER(&exInfo);
54645464

5465+
pThread->IncPreventAbort();
5466+
54655467
//Ex.RhThrowHwEx(exceptionCode, &exInfo)
54665468
CALL_MANAGED_METHOD_NORET(args)
54675469

@@ -5555,6 +5557,8 @@ VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable)
55555557
args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(throwable);
55565558
args[ARGNUM_1] = PTR_TO_ARGHOLDER(&exInfo);
55575559

5560+
pThread->IncPreventAbort();
5561+
55585562
//Ex.RhThrowEx(throwable, &exInfo)
55595563
CRITICAL_CALLSITE;
55605564
CALL_MANAGED_METHOD_NORET(args)
@@ -7559,11 +7563,13 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio
75597563
GCX_COOP_NO_DTOR();
75607564

75617565
Thread* pThread = GET_THREAD();
7566+
pThread->DecPreventAbort();
7567+
75627568
Frame* pFrame = pThread->GetFrame();
75637569
MarkInlinedCallFrameAsFuncletCall(pFrame);
75647570
HandlerFn* pfnHandler = (HandlerFn*)pHandlerIP;
75657571
exInfo->m_sfHighBound = exInfo->m_frameIter.m_crawl.GetRegisterSet()->SP;
7566-
DWORD_PTR dwResumePC;
7572+
DWORD_PTR dwResumePC = 0;
75677573

75687574
if (pHandlerIP != NULL)
75697575
{
@@ -7643,6 +7649,29 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio
76437649
ExceptionTracker::UpdateNonvolatileRegisters(pvRegDisplay->pCurrentContext, pvRegDisplay, FALSE);
76447650
if (pHandlerIP != NULL)
76457651
{
7652+
CopyOSContext(pThread->m_OSContext, pvRegDisplay->pCurrentContext);
7653+
SetIP(pThread->m_OSContext, (PCODE)dwResumePC);
7654+
UINT_PTR uAbortAddr = (UINT_PTR)COMPlusCheckForAbort(dwResumePC);
7655+
if (uAbortAddr)
7656+
{
7657+
#ifdef TARGET_AMD64
7658+
#ifdef TARGET_UNIX
7659+
pvRegDisplay->pCurrentContext->Rdi = dwResumePC;
7660+
pvRegDisplay->pCurrentContext->Rsi = GetIP(pThread->GetAbortContext()); //How can this ever be different from dwResumePC?
7661+
#else
7662+
pvRegDisplay->pCurrentContext->Rcx = dwResumePC;
7663+
#endif
7664+
#elif defined(TARGET_ARM) || defined(TARGET_ARM64)
7665+
// On ARM & ARM64, we save off the original PC in Lr. This is the same as done
7666+
// in HandleManagedFault for H/W generated exceptions.
7667+
pvRegDisplay->pCurrentContext->Lr = dwResumePC;
7668+
#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
7669+
pvRegDisplay->pCurrentContext->Ra = dwResumePC;
7670+
#endif
7671+
7672+
SetIP(pvRegDisplay->pCurrentContext, uAbortAddr);
7673+
}
7674+
76467675
ClrRestoreNonvolatileContext(pvRegDisplay->pCurrentContext);
76477676
}
76487677
else
@@ -7709,6 +7738,8 @@ extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvReg
77097738
BEGIN_QCALL;
77107739
GCX_COOP();
77117740
Thread* pThread = GET_THREAD();
7741+
pThread->DecPreventAbort();
7742+
77127743
Frame* pFrame = pThread->GetFrame();
77137744
MarkInlinedCallFrameAsFuncletCall(pFrame);
77147745
HandlerFn* pfnHandler = (HandlerFn*)pHandlerIP;
@@ -7733,6 +7764,9 @@ extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvReg
77337764
#else
77347765
DWORD_PTR dwResumePC = pfnHandler(establisherFrame, NULL);
77357766
#endif
7767+
7768+
pThread->IncPreventAbort();
7769+
77367770
// Profiler, debugger and ETW events
77377771
exInfo->MakeCallbacksRelatedToHandler(false, pThread, pMD, &exInfo->m_CurrentClause, (DWORD_PTR)pHandlerIP, GetSP(pvRegDisplay->pCurrentContext) );
77387772
END_QCALL;

src/coreclr/vm/jithelpers.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4317,6 +4317,8 @@ void RethrowNew()
43174317
args[ARGNUM_0] = PTR_TO_ARGHOLDER(pActiveExInfo);
43184318
args[ARGNUM_1] = PTR_TO_ARGHOLDER(&exInfo);
43194319

4320+
pThread->IncPreventAbort();
4321+
43204322
//Ex.RhRethrow(ref ExInfo activeExInfo, ref ExInfo exInfo)
43214323
CALL_MANAGED_METHOD_NORET(args)
43224324
GCPROTECT_END();

src/coreclr/vm/threads.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,7 @@ Thread::Thread()
15051505
#endif // TRACK_SYNC
15061506

15071507
m_PreventAsync = 0;
1508+
m_PreventAbort = 0;
15081509
#ifdef FEATURE_COMINTEROP
15091510
m_fDisableComObjectEagerCleanup = false;
15101511
#endif //FEATURE_COMINTEROP

src/coreclr/vm/threads.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2829,6 +2829,29 @@ class Thread
28292829

28302830
typedef StateHolder<Thread::IncPreventAsync, Thread::DecPreventAsync> ThreadPreventAsyncHolder;
28312831

2832+
// While executing the new exception handling managed code,
2833+
// this thread must not be aborted.
2834+
static void IncPreventAbort()
2835+
{
2836+
WRAPPER_NO_CONTRACT;
2837+
Thread *pThread = GetThread();
2838+
InterlockedIncrement((LONG*)&pThread->m_PreventAbort);
2839+
}
2840+
static void DecPreventAbort()
2841+
{
2842+
WRAPPER_NO_CONTRACT;
2843+
Thread *pThread = GetThread();
2844+
#ifdef _DEBUG
2845+
LONG c =
2846+
#endif // _DEBUG
2847+
InterlockedDecrement((LONG*)&pThread->m_PreventAbort);
2848+
_ASSERTE(c >= 0);
2849+
}
2850+
2851+
BOOL IsAbortPrevented()
2852+
{
2853+
return m_PreventAbort != 0;
2854+
}
28322855
// The ThreadStore manages a list of all the threads in the system. I
28332856
// can't figure out how to expand the ThreadList template type without
28342857
// making m_Link public.
@@ -3643,6 +3666,8 @@ class Thread
36433666
// Don't allow a thread to be asynchronously stopped or interrupted (e.g. because
36443667
// it is performing a <clinit>)
36453668
int m_PreventAsync;
3669+
// Don't allow a thread to be aborted while running the new exception handling managed code
3670+
int m_PreventAbort;
36463671

36473672
static LONG m_DebugWillSyncCount;
36483673

src/coreclr/vm/threadsuspend.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -955,9 +955,8 @@ BOOL Thread::ReadyForAsyncException()
955955
}
956956

957957
#ifdef FEATURE_EH_FUNCLETS
958-
if (g_isNewExceptionHandlingEnabled)
958+
if (g_isNewExceptionHandlingEnabled && IsAbortPrevented())
959959
{
960-
// TODO: make thread abort work for the new exception handling
961960
return FALSE;
962961
}
963962
#endif // FEATURE_EH_FUNCLETS

0 commit comments

Comments
 (0)