@@ -2919,6 +2919,7 @@ static void TerminateIPCManager(void)
2919
2919
// Impl for UtilLoadStringRC Callback: In VM, we let the thread decide culture
2920
2920
// copy culture name into szBuffer and return length
2921
2921
// ---------------------------------------------------------------------------
2922
+ extern BOOL g_fFatalErrorOccuredOnGCThread;
2922
2923
static HRESULT GetThreadUICultureNames (__inout StringArrayList* pCultureNames)
2923
2924
{
2924
2925
CONTRACTL
@@ -2941,7 +2942,23 @@ static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames)
2941
2942
2942
2943
Thread * pThread = GetThread ();
2943
2944
2944
- if (pThread != NULL ) {
2945
+ // When fatal errors have occured our invariants around GC modes may be broken and attempting to transition to co-op may hang
2946
+ // indefinately. We want to ensure a clean exit so rather than take the risk of hang we take a risk of the error resource not
2947
+ // getting localized with a non-default thread-specific culture.
2948
+ // A canonical stack trace that gets here is a fatal error in the GC that comes through:
2949
+ // coreclr.dll!GetThreadUICultureNames
2950
+ // coreclr.dll!CCompRC::LoadLibraryHelper
2951
+ // coreclr.dll!CCompRC::LoadLibrary
2952
+ // coreclr.dll!CCompRC::GetLibrary
2953
+ // coreclr.dll!CCompRC::LoadString
2954
+ // coreclr.dll!CCompRC::LoadString
2955
+ // coreclr.dll!SString::LoadResourceAndReturnHR
2956
+ // coreclr.dll!SString::LoadResourceAndReturnHR
2957
+ // coreclr.dll!SString::LoadResource
2958
+ // coreclr.dll!EventReporter::EventReporter
2959
+ // coreclr.dll!EEPolicy::LogFatalError
2960
+ // coreclr.dll!EEPolicy::HandleFatalError
2961
+ if (pThread != NULL && !g_fFatalErrorOccuredOnGCThread) {
2945
2962
2946
2963
// Switch to cooperative mode, since we'll be looking at managed objects
2947
2964
// and we don't want them moving on us.
@@ -3071,8 +3088,24 @@ static int GetThreadUICultureId(__out LocaleIDValue* pLocale)
3071
3088
3072
3089
Thread * pThread = GetThread ();
3073
3090
3074
- if (pThread != NULL ) {
3075
-
3091
+ // When fatal errors have occured our invariants around GC modes may be broken and attempting to transition to co-op may hang
3092
+ // indefinately. We want to ensure a clean exit so rather than take the risk of hang we take a risk of the error resource not
3093
+ // getting localized with a non-default thread-specific culture.
3094
+ // A canonical stack trace that gets here is a fatal error in the GC that comes through:
3095
+ // coreclr.dll!GetThreadUICultureNames
3096
+ // coreclr.dll!CCompRC::LoadLibraryHelper
3097
+ // coreclr.dll!CCompRC::LoadLibrary
3098
+ // coreclr.dll!CCompRC::GetLibrary
3099
+ // coreclr.dll!CCompRC::LoadString
3100
+ // coreclr.dll!CCompRC::LoadString
3101
+ // coreclr.dll!SString::LoadResourceAndReturnHR
3102
+ // coreclr.dll!SString::LoadResourceAndReturnHR
3103
+ // coreclr.dll!SString::LoadResource
3104
+ // coreclr.dll!EventReporter::EventReporter
3105
+ // coreclr.dll!EEPolicy::LogFatalError
3106
+ // coreclr.dll!EEPolicy::HandleFatalError
3107
+ if (pThread != NULL && !g_fFatalErrorOccuredOnGCThread)
3108
+ {
3076
3109
// Switch to cooperative mode, since we'll be looking at managed objects
3077
3110
// and we don't want them moving on us.
3078
3111
GCX_COOP ();
@@ -3130,7 +3163,24 @@ static int GetThreadUICultureId(__out LocaleIDValue* pLocale)
3130
3163
3131
3164
Thread * pThread = GetThread ();
3132
3165
3133
- if (pThread != NULL ) {
3166
+ // When fatal errors have occured our invariants around GC modes may be broken and attempting to transition to co-op may hang
3167
+ // indefinately. We want to ensure a clean exit so rather than take the risk of hang we take a risk of the error resource not
3168
+ // getting localized with a non-default thread-specific culture.
3169
+ // A canonical stack trace that gets here is a fatal error in the GC that comes through:
3170
+ // coreclr.dll!GetThreadUICultureNames
3171
+ // coreclr.dll!CCompRC::LoadLibraryHelper
3172
+ // coreclr.dll!CCompRC::LoadLibrary
3173
+ // coreclr.dll!CCompRC::GetLibrary
3174
+ // coreclr.dll!CCompRC::LoadString
3175
+ // coreclr.dll!CCompRC::LoadString
3176
+ // coreclr.dll!SString::LoadResourceAndReturnHR
3177
+ // coreclr.dll!SString::LoadResourceAndReturnHR
3178
+ // coreclr.dll!SString::LoadResource
3179
+ // coreclr.dll!EventReporter::EventReporter
3180
+ // coreclr.dll!EEPolicy::LogFatalError
3181
+ // coreclr.dll!EEPolicy::HandleFatalError
3182
+ if (pThread != NULL && !g_fFatalErrorOccuredOnGCThread)
3183
+ {
3134
3184
3135
3185
// Switch to cooperative mode, since we'll be looking at managed objects
3136
3186
// and we don't want them moving on us.
0 commit comments