diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs index 6382e21922029..2d782048c0147 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs @@ -253,6 +253,13 @@ private bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError) { if (HasStarted()) throw new ThreadStateException(); + + // Compat: Disallow resetting the initial apartment state + if (_initialApartmentState == state) + return true; + if (_initialApartmentState != ApartmentState.Unknown) + return false; + _initialApartmentState = state; return true; } diff --git a/src/coreclr/vm/comsynchronizable.cpp b/src/coreclr/vm/comsynchronizable.cpp index 1d7fcf8b15c2c..839b957e9d300 100644 --- a/src/coreclr/vm/comsynchronizable.cpp +++ b/src/coreclr/vm/comsynchronizable.cpp @@ -686,25 +686,11 @@ FCIMPL2(INT32, ThreadNative::SetApartmentState, ThreadBaseObject* pThisUNSAFE, I if (pThisUNSAFE==NULL) FCThrowRes(kNullReferenceException, W("NullReference_This")); - INT32 retVal = ApartmentUnknown; BOOL ok = TRUE; THREADBASEREF pThis = (THREADBASEREF) pThisUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_1(pThis); - // Translate state input. ApartmentUnknown is not an acceptable input state. - // Throw an exception here rather than pass it through to the internal - // routine, which asserts. - Thread::ApartmentState state = Thread::AS_Unknown; - if (iState == ApartmentSTA) - state = Thread::AS_InSTA; - else if (iState == ApartmentMTA) - state = Thread::AS_InMTA; - else if (iState == ApartmentUnknown) - state = Thread::AS_Unknown; - else - COMPlusThrow(kArgumentOutOfRangeException, W("ArgumentOutOfRange_Enum")); - Thread *thread = pThis->GetInternal(); if (!thread) COMPlusThrow(kThreadStateException, IDS_EE_THREAD_CANNOT_GET); @@ -722,7 +708,7 @@ FCIMPL2(INT32, ThreadNative::SetApartmentState, ThreadBaseObject* pThisUNSAFE, I { EX_TRY { - state = thread->SetApartment(state); + iState = thread->SetApartment((Thread::ApartmentState)iState); } EX_CATCH { @@ -735,24 +721,13 @@ FCIMPL2(INT32, ThreadNative::SetApartmentState, ThreadBaseObject* pThisUNSAFE, I pThis->LeaveObjMonitor(); } - // Now it's safe to throw exceptions again. if (!ok) COMPlusThrow(kThreadStateException); - // Translate state back into external form - if (state == Thread::AS_InSTA) - retVal = ApartmentSTA; - else if (state == Thread::AS_InMTA) - retVal = ApartmentMTA; - else if (state == Thread::AS_Unknown) - retVal = ApartmentUnknown; - else - _ASSERTE(!"Invalid state returned from SetApartment"); - HELPER_METHOD_FRAME_END(); - return retVal; + return iState; } FCIMPLEND @@ -780,10 +755,10 @@ FCIMPL1(INT32, ThreadNative::GetApartmentState, ThreadBaseObject* pThisUNSAFE) COMPlusThrow(kThreadStateException, W("ThreadState_Dead_State")); } - Thread::ApartmentState state = thread->GetApartment(); + retVal = thread->GetApartment(); #ifdef FEATURE_COMINTEROP - if (state == Thread::AS_Unknown) + if (retVal == Thread::AS_Unknown) { // If the CLR hasn't started COM yet, start it up and attempt the call again. // We do this in order to minimize the number of situations under which we return @@ -791,30 +766,11 @@ FCIMPL1(INT32, ThreadNative::GetApartmentState, ThreadBaseObject* pThisUNSAFE) if (!g_fComStarted) { EnsureComStarted(); - state = thread->GetApartment(); + retVal = thread->GetApartment(); } } #endif // FEATURE_COMINTEROP - // Translate state into external form - retVal = ApartmentUnknown; - if (state == Thread::AS_InSTA) - { - retVal = ApartmentSTA; - } - else if (state == Thread::AS_InMTA) - { - retVal = ApartmentMTA; - } - else if (state == Thread::AS_Unknown) - { - retVal = ApartmentUnknown; - } - else - { - _ASSERTE(!"Invalid state returned from GetApartment"); - } - HELPER_METHOD_FRAME_END(); return retVal; diff --git a/src/coreclr/vm/comsynchronizable.h b/src/coreclr/vm/comsynchronizable.h index 43f998d0055af..889f99c6f3e72 100644 --- a/src/coreclr/vm/comsynchronizable.h +++ b/src/coreclr/vm/comsynchronizable.h @@ -52,13 +52,6 @@ friend class ThreadBaseObject; ThreadAbortRequested = 128, }; - enum - { - ApartmentSTA = 0, - ApartmentMTA = 1, - ApartmentUnknown = 2 - }; - static FCDECL1(INT32, GetPriority, ThreadBaseObject* pThisUNSAFE); static FCDECL2(void, SetPriority, ThreadBaseObject* pThisUNSAFE, INT32 iPriority); static FCDECL1(void, Interrupt, ThreadBaseObject* pThisUNSAFE); diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index ee2ca0a1de948..5aed74ef5124e 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -2654,7 +2654,9 @@ class Thread // undecided. The last state may indicate that the apartment has not been set at // all (nobody has called CoInitializeEx) or that the EE does not know the // current state (EE has not called CoInitializeEx). + // Keep in sync with System.Threading.ApartmentState enum ApartmentState { AS_InSTA, AS_InMTA, AS_Unknown }; + ApartmentState GetApartment(); ApartmentState GetApartmentRare(Thread::ApartmentState as); ApartmentState GetExplicitApartment(); diff --git a/src/libraries/System.Threading.Thread/tests/ThreadTests.cs b/src/libraries/System.Threading.Thread/tests/ThreadTests.cs index 43204224c3ef9..bb54dd600f3b8 100644 --- a/src/libraries/System.Threading.Thread/tests/ThreadTests.cs +++ b/src/libraries/System.Threading.Thread/tests/ThreadTests.cs @@ -253,7 +253,6 @@ public static void GetSetApartmentStateTest_ChangeAfterThreadStarted_Windows( [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] [ActiveIssue("https://github.com/dotnet/runtime/issues/34543", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/72232", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] [MemberData(nameof(ApartmentStateTest_MemberData))] [PlatformSpecific(TestPlatforms.Windows)] // Expected behavior differs on Unix and Windows public static void ApartmentStateTest_ChangeBeforeThreadStarted_Windows( @@ -278,7 +277,6 @@ public static void ApartmentStateTest_ChangeBeforeThreadStarted_Windows( [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsWindowsNanoServer))] [MemberData(nameof(ApartmentStateTest_MemberData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/72232", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] public static void ApartmentStateTest_ChangeBeforeThreadStarted_Windows_Nano_Server( Func getApartmentState, Func setApartmentState,