Skip to content

GlobalizationNative_LoadICUData never called when using Invariant mode (Mac Catalyst and other Apple platforms) #2759

@rolfbjarne

Description

@rolfbjarne

Description

The problem occurs on Apple platforms (Mac Catalyst, iOS) when using .NET 7.

The initial symptom I get is this exception at startup:

Arg_ExternalException (System.Runtime.InteropServices.ExternalException)
   at System.Globalization.CompareInfo.SortHandleCache.GetCachedSortHandle(String )
   at System.Globalization.CompareInfo.IcuInitSortHandle(String )
   at System.Globalization.CompareInfo.InitSort(CultureInfo )
   at System.Globalization.CompareInfo..ctor(CultureInfo )
   at System.Globalization.CultureInfo.get_CompareInfo()
   at System.Globalization.CompareInfo..cctor()

Debugging in lldb shows that this occurs due to an error in ICU, the udata_openChoice function returns an error here:

(lldb) bt
* thread dotnet/runtime#1, name = 'tid_103', queue = 'com.apple.main-thread', stop reason = breakpoint 11.1
  * frame #0: 0x00000001015860e7 libmonosgen-2.0.dylib`udata_openChoice
    frame dotnet/runtime#1: 0x000000010167272e libmonosgen-2.0.dylib`icu::CollationRoot::load(UErrorCode&) + 118
    frame dotnet/runtime#2: 0x000000010164d871 libmonosgen-2.0.dylib`icu::umtx_initOnce(icu::UInitOnce&, void (*)(UErrorCode&), UErrorCode&) + 49
    frame dotnet/runtime#3: 0x0000000101672815 libmonosgen-2.0.dylib`icu::CollationRoot::getRootCacheEntry(UErrorCode&) + 31
    frame dotnet/runtime#4: 0x00000001016600f0 libmonosgen-2.0.dylib`icu::CollationLoader::loadTailoring(icu::Locale const&, UErrorCode&) + 46
    frame dotnet/runtime#5: 0x000000010165d070 libmonosgen-2.0.dylib`icu::Collator::makeInstance(icu::Locale const&, UErrorCode&) + 18
    frame dotnet/runtime#6: 0x000000010165d198 libmonosgen-2.0.dylib`icu::Collator::createInstance(icu::Locale const&, UErrorCode&) + 138
    frame dotnet/runtime#7: 0x0000000101660fcc libmonosgen-2.0.dylib`ucol_open + 74
    frame dotnet/runtime#8: 0x00000001013d0fea libmonosgen-2.0.dylib`GlobalizationNative_GetSortHandle + 74

Debugging a bit more reveals that GlobalizationNative_LoadICUData is never called, and I'm guessing this is the underlying cause for the exceptions above.

Now the question obviously becomes why GlobalizationNative_LoadICUData is never called.

Usually GlobalizationNative_LoadICUData is called like this (for another test app that works fine):

(lldb) monobt
frame #0: 0x0000000101159ac0 libmonosgen-2.0.dylib`GlobalizationNative_LoadICUData
frame dotnet/runtime#1: 0x1009e8140 (wrapper managed-to-native) Interop/Globalization:LoadICUData (string) [{0x11916b828} + 0xf0]  (0x1009e8050 0x1009e8203) [0x600002109180 - MonoTouch]
frame dotnet/runtime#2: 0x1009e800b System.Globalization.GlobalizationMode:LoadICU () [{0x11916a808} + 0x7b]  (0x1009e7f90 0x1009e8011) [0x600002109180 - MonoTouch]
frame dotnet/runtime#3: 0x1009e7453 System.Globalization.GlobalizationMode/Settings:.cctor () [{0x11916a2c0} + 0x113]  (0x1009e7340 0x1009e747d) [0x600002109180 - MonoTouch]
frame dotnet/runtime#4: 0x1009aa4c6 (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr) [{0x101887c88} + 0xa6]  (0x1009aa420 0x1009aa5a8) [0x600002109180 - MonoTouch]
frame dotnet/runtime#5: 0x0000000101169efb libmonosgen-2.0.dylib`mono_jit_runtime_invoke + 2395
frame dotnet/runtime#6: 0x0000000101086a6f libmonosgen-2.0.dylib`mono_runtime_try_invoke + 143
frame dotnet/runtime#7: 0x0000000101085516 libmonosgen-2.0.dylib`mono_runtime_class_init_full + 886
frame dotnet/runtime#8: 0x00000001011617ca libmonosgen-2.0.dylib`mono_jit_compile_method_inner + 1178
frame dotnet/runtime#9: 0x0000000101165d37 libmonosgen-2.0.dylib`jit_compile_method_with_opt + 2679
frame dotnet/runtime#10: 0x000000010116519a libmonosgen-2.0.dylib`mono_jit_compile_method + 58
frame dotnet/runtime#11: 0x00000001012130b9 libmonosgen-2.0.dylib`common_call_trampoline + 1273
frame dotnet/runtime#12: 0x0000000101212b70 libmonosgen-2.0.dylib`mono_magic_trampoline + 96
frame dotnet/runtime#13: 0x100835396<0x100835396 - generic_trampoline_jit trampoline>
frame dotnet/runtime#14: 0x1009e72e3 System.Globalization.GlobalizationMode:get_Invariant () [{0x11916a150} + 0x33]  (0x1009e72b0 0x1009e72e5) [0x600002109180 - MonoTouch]
frame dotnet/runtime#15: 0x1009e6f23 System.Globalization.CultureData:CreateCultureWithInvariantData () [{0x119165778} + 0xed3]  (0x1009e6050 0x1009e71e8) [0x600002109180 - MonoTouch]
frame dotnet/runtime#16: 0x1009e4ef3 System.Globalization.CultureData:get_Invariant () [{0x119164f40} + 0x53]  (0x1009e4ea0 0x1009e4f0f) [0x600002109180 - MonoTouch]
frame dotnet/runtime#17: 0x1009e4dcb System.Globalization.CultureInfo:.cctor () [{0x119164818} + 0x3b]  (0x1009e4d90 0x1009e4e1e) [0x600002109180 - MonoTouch]
frame dotnet/runtime#18: 0x1009aa4c6 (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr) [{0x101887c88} + 0xa6]  (0x1009aa420 0x1009aa5a8) [0x600002109180 - MonoTouch]
frame dotnet/runtime#19: 0x0000000101169efb libmonosgen-2.0.dylib`mono_jit_runtime_invoke + 2395
frame dotnet/runtime#20: 0x0000000101086a6f libmonosgen-2.0.dylib`mono_runtime_try_invoke + 143
frame dotnet/runtime#21: 0x0000000101085516 libmonosgen-2.0.dylib`mono_runtime_class_init_full + 886
frame dotnet/runtime#22: 0x0000000101190a16 libmonosgen-2.0.dylib`mono_method_to_ir + 104182
frame dotnet/runtime#23: 0x000000010115e99d libmonosgen-2.0.dylib`mini_method_compile + 3821
frame dotnet/runtime#24: 0x000000010116136f libmonosgen-2.0.dylib`mono_jit_compile_method_inner + 63
frame dotnet/runtime#25: 0x0000000101165d37 libmonosgen-2.0.dylib`jit_compile_method_with_opt + 2679
frame dotnet/runtime#26: 0x000000010116519a libmonosgen-2.0.dylib`mono_jit_compile_method + 58
frame dotnet/runtime#27: 0x00000001012130b9 libmonosgen-2.0.dylib`common_call_trampoline + 1273
frame dotnet/runtime#28: 0x0000000101212b70 libmonosgen-2.0.dylib`mono_magic_trampoline + 96
frame dotnet/runtime#29: 0x100835396<0x100835396 - generic_trampoline_jit trampoline>
frame dotnet/runtime#30: 0x1009e4d63 System.Globalization.CompareInfo:.cctor () [{0x119164e28} + 0x33]  (0x1009e4d30 0x1009e4d81) [0x600002109180 - MonoTouch]
frame dotnet/runtime#31: 0x1009aa4c6 (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr) [{0x101887c88} + 0xa6]  (0x1009aa420 0x1009aa5a8) [0x600002109180 - MonoTouch]
frame dotnet/runtime#32: 0x0000000101169efb libmonosgen-2.0.dylib`mono_jit_runtime_invoke + 2395
frame dotnet/runtime#33: 0x0000000101086a6f libmonosgen-2.0.dylib`mono_runtime_try_invoke + 143
frame dotnet/runtime#34: 0x0000000101085516 libmonosgen-2.0.dylib`mono_runtime_class_init_full + 886
frame dotnet/runtime#35: 0x0000000101190a16 libmonosgen-2.0.dylib`mono_method_to_ir + 104182
frame dotnet/runtime#36: 0x000000010115e99d libmonosgen-2.0.dylib`mini_method_compile + 3821
frame dotnet/runtime#37: 0x000000010116136f libmonosgen-2.0.dylib`mono_jit_compile_method_inner + 63
frame dotnet/runtime#38: 0x0000000101165d37 libmonosgen-2.0.dylib`jit_compile_method_with_opt + 2679
frame dotnet/runtime#39: 0x000000010116519a libmonosgen-2.0.dylib`mono_jit_compile_method + 58
frame dotnet/runtime#40: 0x00000001012130b9 libmonosgen-2.0.dylib`common_call_trampoline + 1273
frame dotnet/runtime#41: 0x0000000101212b70 libmonosgen-2.0.dylib`mono_magic_trampoline + 96
frame dotnet/runtime#42: 0x100835396<0x100835396 - generic_trampoline_jit trampoline>
frame dotnet/runtime#43: 0x1009e4cd3 string:StartsWith (string) [{0x1018baa80} + 0x53]  (0x1009e4c80 0x1009e4d13) [0x600002109180 - MonoTouch]
frame dotnet/runtime#44: 0x1009e4abb ObjCRuntime.Runtime:GetIsARM64CallingConvention () [{0x119061c48} + 0x6b]  (0x1009e4a50 0x1009e4abd) [0x600002109180 - MonoTouch]
frame dotnet/runtime#45: 0x1009b390b ObjCRuntime.Runtime:Initialize (ObjCRuntime.Runtime/InitializationOptions*) [{0x119013508} + 0x30b]  (0x1009b3600 0x1009b3a13) [0x600002109180 - MonoTouch]
frame dotnet/runtime#46: 0x1009b3b91 (wrapper runtime-invoke) <Module>:runtime_invoke_void_Runtime/InitializationOptions* (object,intptr,intptr,intptr) [{0x119061a80} + 0xb1]  (0x1009b3ae0 0x1009b3c78) [0x600002109180 - MonoTouch]
frame dotnet/runtime#47: 0x0000000101169efb libmonosgen-2.0.dylib`mono_jit_runtime_invoke + 2395
frame dotnet/runtime#48: 0x0000000101086a6f libmonosgen-2.0.dylib`mono_runtime_try_invoke + 143
frame dotnet/runtime#49: 0x0000000101088dff libmonosgen-2.0.dylib`mono_runtime_invoke + 95
frame dotnet/runtime#50: 0x0000000100a37c0e libxamarin-dotnet-debug.dylib`xamarin_bridge_call_runtime_initialize(options=0x0000000100a4b9f0, exception_gchandle=0x00007ff7bfeff1f0) at monovm-bridge.m:147:2
frame dotnet/runtime#51: 0x0000000100a2a87c libxamarin-dotnet-debug.dylib`xamarin_initialize at runtime.m:1302:2
frame dotnet/runtime#52: 0x0000000100a3dbe1 libxamarin-dotnet-debug.dylib`xamarin_main(argc=1, argv=0x00007ff7bfeff448, launch_mode=XamarinLaunchModeApp) at monotouch-main.m:438:2
frame dotnet/runtime#53: 0x00000001000aafc4 BundleStructure`main(argc=1, argv=0x00007ff7bfeff448) at main.x86_64.mm:62:11
frame dotnet/runtime#54: 0x00000001004e551e dyld`start + 462

So I traced all managed code (setting MONO_TRACE=all): iTerm2 Session 20 Apr 2022 at 6:28:03 PM.txt.zip

And I found that:

  1. System.Globalization.GlobalizationMode/Settings:.cctor is never called.
  2. System.Globalization.GlobalizationMode:get_Invariant is never called.
  3. However, System.Globalization.CultureData:CreateCultureWithInvariantData is called.

Then I compared the IL for System.Globalization.CultureData:CreateCultureWithInvariantData between a working app and a failing app, and it turns out there's no call to System.Globalization.GlobalizationMode:get_Invariant in the failing app.

I'm guessing the linker linked it away.

App that fails: BundleStructure.app.zip - download, unzip, and execute ./BundleStructure.app/Contents/MacOS/BundleStructure in Terminal to see the exception (due to a different issue on our side the app ends up in an infinite loop, but this is the cause for the loop in the first place).

Note: this is not a problem in .NET 6, only in .NET 7.

Reproduction Steps

If the above description isn't enough, I can try to find a way to reproduce it.

Expected behavior

No exception at startup

Actual behavior

See above

Regression?

Yes.

This started happened when maestro did this bump: dotnet/macios@d9eacac.

Known Workarounds

No response

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions