bug-gettext
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Forced crash under macOS 14 due to internal threading


From: Bruno Haible
Subject: Re: Forced crash under macOS 14 due to internal threading
Date: Fri, 03 May 2024 15:44:03 +0200

Hi,

> Running the following:
> 
> ```
> #include <libintl.h>
> #include <stdlib.h>
> #include <unistd.h>
> 
> int main() {
>   unsetenv("LANG");
> 
>   setlocale(LC_ALL, "");
> 
>   if (fork() == 0) {
>     gettext("test");
>   }
> }
> ```
> 
> under macos14, crashes with the following error:
> 
> ```
> objc[16942]: +[__SwiftNativeNSStringBase initialize] may have been in 
> progress in another thread when fork() was called.
> objc[16942]: +[__SwiftNativeNSStringBase initialize] may have been in 
> progress in another thread when fork() was called. We cannot safely call it 
> or ignore it in the fork() child process. Crashing instead. Set a breakpoint 
> on objc_initializeAfterForkError to debug.
> ```
> 
> The call to `setlocale` spawns threads (via `dispatch_apply`) with the 
> following backtrace:
> 
> ```
> * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
>   * frame #0: 0x0000000182c5602c libdispatch.dylib`dispatch_apply
>     frame #1: 0x0000000183000af0 
> CoreFoundation`__103-[CFPrefsSearchListSource 
> synchronouslySendSystemMessage:andUserMessage:andDirectMessage:replyHandler:]_block_invoke.52
>  + 132
>     frame #2: 0x0000000182e86cbc 
> CoreFoundation`CFPREFERENCES_IS_WAITING_FOR_SYSTEM_AND_USER_CFPREFSDS + 100
>     frame #3: 0x0000000182fffce0 CoreFoundation`-[CFPrefsSearchListSource 
> synchronouslySendSystemMessage:andUserMessage:andDirectMessage:replyHandler:] 
> + 232
>     frame #4: 0x0000000182e84f68 CoreFoundation`-[CFPrefsSearchListSource 
> alreadylocked_generationCountFromListOfSources:count:] + 232
>     frame #5: 0x0000000182e84c70 CoreFoundation`-[CFPrefsSearchListSource 
> alreadylocked_getDictionary:] + 492
>     frame #6: 0x0000000182e847dc CoreFoundation`-[CFPrefsSearchListSource 
> alreadylocked_copyValueForKey:] + 172
>     frame #7: 0x0000000182e84710 CoreFoundation`-[CFPrefsSource 
> copyValueForKey:] + 52
>     frame #8: 0x0000000182e846c4 CoreFoundation`__76-[_CFXPreferences 
> copyAppValueForKey:identifier:container:configurationURL:]_block_invoke + 32
>     frame #9: 0x0000000182e7dd00 
> CoreFoundation`__108-[_CFXPreferences(SearchListAdditions) 
> withSearchListForIdentifier:container:cloudConfigurationURL:perform:]_block_invoke
>  + 376
>     frame #10: 0x00000001830013a0 CoreFoundation`-[_CFXPreferences 
> withSearchListForIdentifier:container:cloudConfigurationURL:perform:] + 384
>     frame #11: 0x0000000182e7d5d8 CoreFoundation`-[_CFXPreferences 
> copyAppValueForKey:identifier:container:configurationURL:] + 156
>     frame #12: 0x0000000182e7d500 
> CoreFoundation`_CFPreferencesCopyAppValueWithContainerAndConfiguration + 112
>     frame #13: 0x00000001004827e4 
> libintl.8.dylib`_libintl_locale_name_default + 72
>     frame #14: 0x0000000100481990 libintl.8.dylib`libintl_setlocale + 164
>     frame #15: 0x0000000100003f38 main`main + 52
>     frame #16: 0x0000000182a6a0e0 dyld`start + 2360
> ```
> 
> and the call to `gettext` triggers this crash (via 
> `performForkChildInitialize`) with the following backtrace:
> 
> ```
> * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
>   * frame #0: 0x0000000182a382c4 libobjc.A.dylib`objc_initializeAfterForkError
>     frame #1: 0x0000000182a38448 
> libobjc.A.dylib`performForkChildInitialize(objc_class*, objc_class*) + 376
>     frame #2: 0x0000000182a1eba4 libobjc.A.dylib`initializeNonMetaClass + 572
>     frame #3: 0x0000000182a1ea04 libobjc.A.dylib`initializeNonMetaClass + 156
>     frame #4: 0x0000000182a1ea04 libobjc.A.dylib`initializeNonMetaClass + 156
>     frame #5: 0x0000000182a3bbfc 
> libobjc.A.dylib`initializeAndMaybeRelock(objc_class*, objc_object*, 
> locker_mixin<lockdebug::lock_mixin<objc_lock_base_t>>&, bool) + 164
>     frame #6: 0x0000000182a1e5c4 libobjc.A.dylib`lookUpImpOrForward + 892
>     frame #7: 0x0000000182a1df64 libobjc.A.dylib`_objc_msgSend_uncached + 68
>     frame #8: 0x0000000192dfbbc8 libswiftCore.dylib`type metadata accessor 
> for Swift.__StringStorage + 24
>     frame #9: 0x0000000192b85f24 
> libswiftCore.dylib`Swift.String._bridgeToObjectiveCImpl() -> Swift.AnyObject 
> + 152
>     frame #10: 0x0000000184409f80 Foundation`function signature 
> specialization <Arg[1] = Dead> of 
> Foundation.LocaleCache.preferredLanguages(forCurrentUser: Swift.Bool) -> 
> Swift.Array<Swift.String> + 76
>     frame #11: 0x00000001844ec9c4 Foundation`@objc static 
> __C.NSLocale._preferredLanguagesForCurrentUser(Swift.Bool) -> 
> Swift.Array<Swift.String> + 44
>     frame #12: 0x0000000182ece0b4 
> CoreFoundation`CFLocaleCopyPreferredLanguages + 28
>     frame #13: 0x0000000100a553dc 
> libintl.8.dylib`_libintl_language_preferences_default + 68
>     frame #14: 0x0000000100a53d40 libintl.8.dylib`libintl_dcigettext + 812
>     frame #15: 0x00000001005d7f10 main`main + 120
>     frame #16: 0x0000000182a6a0e0 dyld`start + 2360
> ```
> 
> This is the case with `gettext` 0.22.5, 0.21.1 and 0.20.2; 0.19.8.1 does not 
> exhibit this behaviour as it doesn't call `CFLocaleCopyPreferredLanguages`.

Thanks for the report. Both CFLocaleCopyPreferredLanguages and
CFPreferencesCopyAppValue are documented API from Apple [1][2],
with no hints regarding multithreading. I have no idea how to
influence the behaviour of these functions w.r.t. multithreading.
Can you report the issue to Apple, after having replaced the call
to setlocale with a call to

        char namebuf[256];
        CFTypeRef value =
          CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
                                     kCFPreferencesCurrentApplication);

and the call to gettext with a call to

        CFArrayRef prefArray = CFLocaleCopyPreferredLanguages ();

?

Other than that, a workaround can be:

  - In applications use fork+exec, use posix_spawn and posix_spawnp.
  - In applications that fork without exec, move the initializations
    past the fork(), so that at the moment of the fork(), the application
    is still single-threaded.

Bruno

[1] 
https://developer.apple.com/documentation/corefoundation/1542887-cflocalecopypreferredlanguages?language=objc
[2] 
https://developer.apple.com/documentation/corefoundation/1515497-cfpreferencescopyappvalue?language=objc






reply via email to

[Prev in Thread] Current Thread [Next in Thread]