diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs index 594ecbf3c55227..b29bf304f3811b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs @@ -98,13 +98,17 @@ private unsafe void StartCore() { fixed (char* pThreadName = _name) { - StartInternal(GetNativeHandle(), _startHelper?._maxStackSize ?? 0, _priority, _isThreadPool ? Interop.BOOL.TRUE : Interop.BOOL.FALSE, pThreadName); + Exception? exception = null; + if (StartInternal(GetNativeHandle(), _startHelper?._maxStackSize ?? 0, _priority, _isThreadPool ? Interop.BOOL.TRUE : Interop.BOOL.FALSE, pThreadName, ObjectHandleOnStack.Create(ref exception)) == Interop.BOOL.FALSE) + { + throw new ThreadStartException(exception); + } } } } [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_Start")] - private static unsafe partial void StartInternal(ThreadHandle t, int stackSize, int priority, Interop.BOOL isThreadPool, char* pThreadName); + private static unsafe partial Interop.BOOL StartInternal(ThreadHandle t, int stackSize, int priority, Interop.BOOL isThreadPool, char* pThreadName, ObjectHandleOnStack exception); // Called from the runtime private void StartCallback() diff --git a/src/coreclr/vm/comsynchronizable.cpp b/src/coreclr/vm/comsynchronizable.cpp index 643373a5207b2b..fa557eb183b22e 100644 --- a/src/coreclr/vm/comsynchronizable.cpp +++ b/src/coreclr/vm/comsynchronizable.cpp @@ -187,10 +187,12 @@ static ULONG WINAPI KickOffThread(void* pass) return 0; } -extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, BOOL isThreadPool, PCWSTR pThreadName) +extern "C" BOOL QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, BOOL isThreadPool, PCWSTR pThreadName, QCall::ObjectHandleOnStack exception) { QCALL_CONTRACT; + BOOL result = TRUE; + BEGIN_QCALL; Thread* pNewThread = thread; @@ -266,10 +268,13 @@ extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int thr { GCX_COOP(); - pNewThread->HandleThreadStartupFailure(); + result = FALSE; + exception.Set(pNewThread->GetExceptionDuringStartup()); } END_QCALL; + + return result; } extern "C" void QCALLTYPE ThreadNative_SetPriority(QCall::ObjectHandleOnStack thread, INT32 iPriority) diff --git a/src/coreclr/vm/comsynchronizable.h b/src/coreclr/vm/comsynchronizable.h index 16b1fe6d898b7a..c3f86c75d33f54 100644 --- a/src/coreclr/vm/comsynchronizable.h +++ b/src/coreclr/vm/comsynchronizable.h @@ -45,7 +45,7 @@ class ThreadNative static FCDECL0(FC_BOOL_RET, CurrentThreadIsFinalizerThread); }; -extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, BOOL isThreadPool, PCWSTR pThreadName); +extern "C" BOOL QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, BOOL isThreadPool, PCWSTR pThreadName, QCall::ObjectHandleOnStack exception); extern "C" void QCALLTYPE ThreadNative_SetPriority(QCall::ObjectHandleOnStack thread, INT32 iPriority); extern "C" void QCALLTYPE ThreadNative_GetCurrentThread(QCall::ObjectHandleOnStack thread); extern "C" BOOL QCALLTYPE ThreadNative_GetIsBackground(QCall::ThreadHandle thread); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index d243c3a46b54b0..93e80be8c2bec9 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -334,9 +334,6 @@ DEFINE_METHOD(SYSTEM_EXCEPTION, STR_EX_CTOR, .ctor, DEFINE_CLASS(TYPE_INIT_EXCEPTION, System, TypeInitializationException) DEFINE_METHOD(TYPE_INIT_EXCEPTION, STR_EX_CTOR, .ctor, IM_Str_Exception_RetVoid) -DEFINE_CLASS(THREAD_START_EXCEPTION,Threading, ThreadStartException) -DEFINE_METHOD(THREAD_START_EXCEPTION,EX_CTOR, .ctor, IM_Exception_RetVoid) - DEFINE_CLASS(VALUETASK_1, Tasks, ValueTask`1) DEFINE_METHOD(VALUETASK_1, GET_ISCOMPLETED, get_IsCompleted, NoSig) DEFINE_METHOD(VALUETASK_1, GET_RESULT, get_Result, NoSig) diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index fcc8835a49f1e4..1df93c2061ca0c 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -94,8 +94,6 @@ BOOL IsExceptionFromManagedCode(const EXCEPTION_RECORD * pExceptionRecord) PEXCEPTION_REGISTRATION_RECORD GetCurrentSEHRecord(); BOOL IsUnmanagedToManagedSEHHandler(EXCEPTION_REGISTRATION_RECORD*); -VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow); - //------------------------------------------------------------------------------- // Basically, this asks whether the exception is a managed exception thrown by // this instance of the CLR. @@ -1965,61 +1963,6 @@ ReplaceExceptionContextRecord(CONTEXT *pTarget, CONTEXT *pSource) #endif // !CONTEXT_EXTENDED_REGISTERS } -VOID FixupOnRethrow(Thread* pCurThread, EXCEPTION_POINTERS* pExceptionPointers) -{ - WRAPPER_NO_CONTRACT; - - ThreadExceptionState* pExState = pCurThread->GetExceptionState(); - - // Don't allow rethrow of a STATUS_STACK_OVERFLOW -- it's a new throw of the CLR exception. - if (pExState->GetExceptionCode() == STATUS_STACK_OVERFLOW) - { - return; - } - - // For COMPLUS exceptions, we don't need the original context for our rethrow. - if (!(pExState->IsComPlusException())) - { - _ASSERTE(pExState->GetExceptionRecord()); - - // don't copy parm args as have already supplied them on the throw - memcpy((void*)pExceptionPointers->ExceptionRecord, - (void*)pExState->GetExceptionRecord(), - offsetof(EXCEPTION_RECORD, ExceptionInformation)); - } - - pExState->GetFlags()->SetIsRethrown(); -} - -struct RaiseExceptionFilterParam -{ - BOOL isRethrown; -}; - -LONG RaiseExceptionFilter(EXCEPTION_POINTERS* ep, LPVOID pv) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_MODE_ANY; - - RaiseExceptionFilterParam *pParam = (RaiseExceptionFilterParam *) pv; - - if (1 == pParam->isRethrown) - { - // need to reset the EH info back to the original thrown exception - FixupOnRethrow(GetThread(), ep); - - // only do this once - pParam->isRethrown++; - } - else - { - CONSISTENCY_CHECK((2 == pParam->isRethrown) || (0 == pParam->isRethrown)); - } - - return EXCEPTION_CONTINUE_SEARCH; -} - HRESULT GetHRFromThrowable(OBJECTREF throwable) { STATIC_CONTRACT_THROWS; @@ -2041,14 +1984,14 @@ HRESULT GetHRFromThrowable(OBJECTREF throwable) return hr; } -VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable, BOOL rethrow, BOOL fForStackOverflow) +VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable) { STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_MODE_COOPERATIVE; - STRESS_LOG3(LF_EH, LL_INFO100, "******* MANAGED EXCEPTION THROWN: Object thrown: %p MT %pT rethrow %d\n", - OBJECTREFToObject(throwable), (throwable!=0)?throwable->GetMethodTable():0, rethrow); + STRESS_LOG2(LF_EH, LL_INFO100, "******* MANAGED EXCEPTION THROWN: Object thrown: %p MT %pT\n", + OBJECTREFToObject(throwable), (throwable!=0)?throwable->GetMethodTable():0); #ifdef STRESS_LOG // Any object could have been thrown, but System.Exception objects have useful information for the stress log @@ -2071,26 +2014,16 @@ VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable, BOOL r } #endif - struct Param : RaiseExceptionFilterParam - { - OBJECTREF throwable; - BOOL fForStackOverflow; - ULONG_PTR exceptionArgs[INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE]; - Thread *pThread; - ThreadExceptionState* pExState; - } param; - param.isRethrown = rethrow ? 1 : 0; // normalize because we use it as a count in RaiseExceptionFilter - param.throwable = throwable; - param.fForStackOverflow = fForStackOverflow; - param.pThread = GetThread(); + ULONG_PTR exceptionArgs[INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE]; + Thread* pThread = GetThread(); - _ASSERTE(param.pThread); - param.pExState = param.pThread->GetExceptionState(); + _ASSERTE(pThread); + ThreadExceptionState* pExState = pThread->GetExceptionState(); - if (param.pThread->IsRudeAbortInitiated()) + if (pThread->IsRudeAbortInitiated()) { // Nobody should be able to swallow rude thread abort. - param.throwable = CLRException::GetBestThreadAbortException(); + throwable = CLRException::GetBestThreadAbortException(); } #if 0 @@ -2098,7 +2031,7 @@ VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable, BOOL r #ifdef _DEBUG // If ThreadAbort exception is thrown, the thread should be marked with AbortRequest. // If not, we may see unhandled exception. - if (param.throwable->GetMethodTable() == g_pThreadAbortExceptionClass) + if (throwable->GetMethodTable() == g_pThreadAbortExceptionClass) { _ASSERTE(GetThread()->IsAbortRequested() #ifdef TARGET_X86 @@ -2111,76 +2044,41 @@ VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable, BOOL r #endif // raise - PAL_TRY(Param *, pParam, ¶m) - { - //_ASSERTE(! pParam->isRethrown || pParam->pExState->m_pExceptionRecord); - ULONG_PTR *args = NULL; - ULONG argCount = 0; - ULONG flags = 0; - ULONG code = 0; - // Always save the current object in the handle so on rethrow we can reuse it. This is important as it - // contains stack trace info. - // - // Note: we use SafeSetLastThrownObject, which will try to set the throwable and if there are any problems, - // it will set the throwable to something appropriate (like OOM exception) and return the new - // exception. Thus, the user's exception object can be replaced here. - pParam->throwable = pParam->pThread->SafeSetLastThrownObject(pParam->throwable); - - if (!pParam->isRethrown || - pParam->pExState->IsComPlusException() || - (pParam->pExState->GetExceptionCode() == STATUS_STACK_OVERFLOW)) - { - ULONG_PTR hr = GetHRFromThrowable(pParam->throwable); - - args = pParam->exceptionArgs; - argCount = MarkAsThrownByUs(args, hr); - flags = EXCEPTION_NONCONTINUABLE; - code = EXCEPTION_COMPLUS; - } - else - { - // Exception code should be consistent. - _ASSERTE((DWORD)(pParam->pExState->GetExceptionRecord()->ExceptionCode) == pParam->pExState->GetExceptionCode()); + ULONG argCount = 0; + ULONG flags = 0; + ULONG code = 0; - args = pParam->pExState->GetExceptionRecord()->ExceptionInformation; - argCount = pParam->pExState->GetExceptionRecord()->NumberParameters; - flags = pParam->pExState->GetExceptionRecord()->ExceptionFlags; - code = pParam->pExState->GetExceptionRecord()->ExceptionCode; - } + // Always save the current object in the handle so on rethrow we can reuse it. This is important as it + // contains stack trace info. + // + // Note: we use SafeSetLastThrownObject, which will try to set the throwable and if there are any problems, + // it will set the throwable to something appropriate (like OOM exception) and return the new + // exception. Thus, the user's exception object can be replaced here. + throwable = pThread->SafeSetLastThrownObject(throwable); - if (pParam->pThread->IsAbortInitiated () && IsExceptionOfType(kThreadAbortException,&pParam->throwable)) - { - pParam->pThread->ResetPreparingAbort(); + ULONG_PTR hr = GetHRFromThrowable(throwable); - if (pParam->pThread->GetFrame() == FRAME_TOP) - { - // There is no more managed code on stack. - pParam->pThread->ResetAbort(); - } - } + argCount = MarkAsThrownByUs(exceptionArgs, hr); + flags = EXCEPTION_NONCONTINUABLE; + code = EXCEPTION_COMPLUS; - // Can't access the exception object when are in pre-emptive, so find out before - // if its an SO. - BOOL fIsStackOverflow = IsExceptionOfType(kStackOverflowException, &pParam->throwable); + if (pThread->IsAbortInitiated () && IsExceptionOfType(kThreadAbortException,&throwable)) + { + pThread->ResetPreparingAbort(); - if (fIsStackOverflow || pParam->fForStackOverflow) + if (pThread->GetFrame() == FRAME_TOP) { - // Don't probe if we're already handling an SO. Just throw the exception. - RaiseException(code, flags, argCount, args); + // There is no more managed code on stack. + pThread->ResetAbort(); } + } - // This needs to be both here and inside the handler below - // enable preemptive mode before call into OS - GCX_PREEMP_NO_DTOR(); + // Enable preemptive mode before call into OS + GCX_PREEMP_NO_DTOR(); + + RaiseException(code, flags, argCount, exceptionArgs); - // In non-debug, we can just raise the exception once we've probed. - RaiseException(code, flags, argCount, args); - } - PAL_EXCEPT_FILTER (RaiseExceptionFilter) - { - } - PAL_ENDTRY _ASSERTE(!"Cannot continue after CLR exception"); // Debugger can bring you here. // For example, // Debugger breaks in due to second chance exception (unhandled) @@ -2190,7 +2088,7 @@ VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable, BOOL r UNREACHABLE(); } -static VOID DECLSPEC_NORETURN RealCOMPlusThrowWorker(OBJECTREF throwable, BOOL rethrow) +static VOID DECLSPEC_NORETURN RealCOMPlusThrowWorker(OBJECTREF throwable) { STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; @@ -2208,10 +2106,10 @@ static VOID DECLSPEC_NORETURN RealCOMPlusThrowWorker(OBJECTREF throwable, BOOL r EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); } - RaiseTheExceptionInternalOnly(throwable, rethrow); + RaiseTheExceptionInternalOnly(throwable); } -VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow) +VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable) { STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; @@ -2224,41 +2122,18 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow) _ASSERTE(IsException(throwable->GetMethodTable())); - // This may look a bit odd, but there is an explanation. The rethrow boolean - // means that an actual RaiseException(EXCEPTION_COMPLUS,...) is being re-thrown, - // and that the exception context saved on the Thread object should replace - // the exception context from the upcoming RaiseException(). There is logic - // in the stack trace code to preserve MOST of the stack trace, but to drop the - // last element of the stack trace (has to do with having the address of the rethrow - // instead of the address of the original call in the stack trace. That is - // controversial itself, but we won't get into that here.) - // However, if this is not re-raising that original exception, but rather a new + // If this is not re-raising that original exception, but rather a new // os exception for what may be an existing exception object, it is generally // a good thing to preserve the stack trace. - if (!rethrow) - { - Thread *pThread = GetThread(); - pThread->IncPreventAbort(); - ExceptionPreserveStackTrace(throwable); - pThread->DecPreventAbort(); - } - RealCOMPlusThrowWorker(throwable, rethrow); - - GCPROTECT_END(); -} + Thread *pThread = GetThread(); + pThread->IncPreventAbort(); + ExceptionPreserveStackTrace(throwable); + pThread->DecPreventAbort(); -VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } - CONTRACTL_END; + RealCOMPlusThrowWorker(throwable); - RealCOMPlusThrow(throwable, FALSE); + GCPROTECT_END(); } #ifdef TARGET_WASM @@ -2295,7 +2170,7 @@ VOID DECLSPEC_NORETURN __fastcall PropagateExceptionThroughNativeFrames(Object * #else OBJECTREF throwable = ObjectToOBJECTREF(exceptionObj); #endif // TARGET_WASM - RealCOMPlusThrowWorker(throwable, FALSE); + RealCOMPlusThrowWorker(throwable); #ifdef TARGET_WASM } PAL_EXCEPT(SetTargetFrame(ex, __param->targetSP)) @@ -6910,7 +6785,7 @@ VOID DECLSPEC_NORETURN UnwindAndContinueRethrowHelperAfterCatch(Frame* pEntryFra } else { - RaiseTheExceptionInternalOnly(orThrowable, FALSE); + RaiseTheExceptionInternalOnly(orThrowable); } } diff --git a/src/coreclr/vm/exceptmacros.h b/src/coreclr/vm/exceptmacros.h index 7ed917ca75e577..c72b673c898ad5 100644 --- a/src/coreclr/vm/exceptmacros.h +++ b/src/coreclr/vm/exceptmacros.h @@ -191,7 +191,7 @@ VEH_ACTION CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); // Actual UEF worker prototype for use by GCUnhandledExceptionFilter. extern LONG InternalUnhandledExceptionFilter_Worker(PEXCEPTION_POINTERS pExceptionInfo); -VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable, BOOL rethrow, BOOL fForStackOverflow = FALSE); +VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable); #if defined(DACCESS_COMPILE) diff --git a/src/coreclr/vm/exstatecommon.h b/src/coreclr/vm/exstatecommon.h index 7cc933fdc29457..5dfefafac1214d 100644 --- a/src/coreclr/vm/exstatecommon.h +++ b/src/coreclr/vm/exstatecommon.h @@ -289,10 +289,6 @@ class ExceptionFlags m_flags = 0; } - BOOL IsRethrown() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_IsRethrown; } - void SetIsRethrown() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_IsRethrown; } - void ResetIsRethrown() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_IsRethrown; } - BOOL UnwindHasStarted() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_UnwindHasStarted; } void SetUnwindHasStarted() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_UnwindHasStarted; } void ResetUnwindHasStarted() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_UnwindHasStarted; } @@ -348,7 +344,7 @@ class ExceptionFlags private: enum { - Ex_IsRethrown = 0x00000001, + // Unused = 0x00000001, Ex_UnwindingToFindResumeFrame = 0x00000002, Ex_UnwindHasStarted = 0x00000004, Ex_UseExInfoForStackwalk = 0x00000008, // Use this ExInfo to unwind a fault (AV, zerodiv) back to managed code? diff --git a/src/coreclr/vm/rexcep.h b/src/coreclr/vm/rexcep.h index 648a08865d73be..05983f4edaf2f2 100644 --- a/src/coreclr/vm/rexcep.h +++ b/src/coreclr/vm/rexcep.h @@ -241,7 +241,6 @@ DEFINE_EXCEPTION(g_ReflectionNS, TargetParameterCountException, false, C DEFINE_EXCEPTION(g_ThreadingNS, ThreadAbortException, false, COR_E_THREADABORTED) DEFINE_EXCEPTION(g_ThreadingNS, ThreadInterruptedException, false, COR_E_THREADINTERRUPTED) DEFINE_EXCEPTION(g_ThreadingNS, ThreadStateException, false, COR_E_THREADSTATE) -DEFINE_EXCEPTION(g_ThreadingNS, ThreadStartException, false, COR_E_THREADSTART) DEFINE_EXCEPTION(g_SystemNS, TypeAccessException, false, COR_E_TYPEACCESS) DEFINE_EXCEPTION(g_SystemNS, TypeInitializationException, false, COR_E_TYPEINITIALIZATION) diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index ac6642be29b349..00f17de38ab91c 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -1708,8 +1708,7 @@ BOOL Thread::HasStarted() return FALSE; } - -void Thread::HandleThreadStartupFailure() +OBJECTREF Thread::GetExceptionDuringStartup() { CONTRACTL { @@ -1721,37 +1720,11 @@ void Thread::HandleThreadStartupFailure() _ASSERTE(GetThreadNULLOk() != NULL); - struct - { - OBJECTREF pThrowable; - OBJECTREF pReason; - } gc; - gc.pThrowable = NULL; - gc.pReason = NULL; - - GCPROTECT_BEGIN(gc); - - MethodTable *pMT = CoreLibBinder::GetException(kThreadStartException); - gc.pThrowable = AllocateObject(pMT); - - MethodDescCallSite exceptionCtor(METHOD__THREAD_START_EXCEPTION__EX_CTOR); - - if (m_pExceptionDuringStartup) - { - gc.pReason = CLRException::GetThrowableFromException(m_pExceptionDuringStartup); - Exception::Delete(m_pExceptionDuringStartup); - m_pExceptionDuringStartup = NULL; - } - - ARG_SLOT args1[] = { - ObjToArgSlot(gc.pThrowable), - ObjToArgSlot(gc.pReason), - }; - exceptionCtor.Call(args1); - - GCPROTECT_END(); //Prot + OBJECTREF throwable = CLRException::GetThrowableFromException(m_pExceptionDuringStartup); + Exception::Delete(m_pExceptionDuringStartup); + m_pExceptionDuringStartup = NULL; - RaiseTheExceptionInternalOnly(gc.pThrowable, FALSE); + return throwable; } #ifndef TARGET_UNIX diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index 57c2383ce6dbc8..f54ee613485dc6 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -3314,7 +3314,7 @@ class Thread Exception* m_pExceptionDuringStartup; public: - void HandleThreadStartupFailure(); + OBJECTREF GetExceptionDuringStartup(); #ifdef HAVE_GCCOVER private: diff --git a/src/coreclr/vm/threadsuspend.cpp b/src/coreclr/vm/threadsuspend.cpp index 5bae79b9da454c..0dc93643a5985d 100644 --- a/src/coreclr/vm/threadsuspend.cpp +++ b/src/coreclr/vm/threadsuspend.cpp @@ -1195,7 +1195,7 @@ Thread::UserAbort(EEPolicy::ThreadAbortTypes abortType, DWORD timeout) exceptObj = CLRException::GetThrowableFromException(&eeExcept); } - RaiseTheExceptionInternalOnly(exceptObj, FALSE); + RaiseTheExceptionInternalOnly(exceptObj); } _ASSERTE(this != pCurThread); // Aborting another thread. @@ -2247,7 +2247,7 @@ void Thread::HandleThreadAbort () exceptObj = CLRException::GetThrowableFromException(&eeExcept); } - RaiseTheExceptionInternalOnly(exceptObj, FALSE); + RaiseTheExceptionInternalOnly(exceptObj); } ::SetLastError(lastError); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStartException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStartException.cs index cd852825bbe441..71897652c4e5a7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStartException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStartException.cs @@ -16,7 +16,7 @@ internal ThreadStartException() HResult = HResults.COR_E_THREADSTART; } - internal ThreadStartException(Exception reason) + internal ThreadStartException(Exception? reason) : base(SR.Arg_ThreadStartException, reason) { HResult = HResults.COR_E_THREADSTART;