[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
macOS 14 objc `+initialize` forced crash due to fork after thread
From: |
Tom |
Subject: |
macOS 14 objc `+initialize` forced crash due to fork after thread |
Date: |
Thu, 02 May 2024 06:23:00 +0000 |
Forgive me if this is a repost; there appeared to be no path for `bashbug` to
respond to me, so I've sent this manually.
Configuration Information [Automatically generated, do not change]:
Machine: aarch64
OS: darwin23.4.0
Compiler: gcc
Compilation CFLAGS: -g -O2
uname output: Darwin toms-Mac-mini.local 23.4.0 Darwin Kernel Version 23.4.0:
Fri Mar 15 00:12:49 PDT 2024; root:xnu-10063.101.17~1/RELEASE_ARM64_T6020 arm64
Machine Type: aarch64-apple-darwin23.4.0
Bash Version: 5.2
Patch Level: 26
Release Status: release
Description:
When linked against `libintl.8.dylib`, if an unknown comand is executed, the
following error is seen:
```
objc[54525]: +[__SwiftNativeNSStringBase initialize] may have been in progress
in another thread when fork() was called.
objc[54525]: +[__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.
Abort trap: 6
```
This is a synthetic crash caused by the objc runtime whenever a static
initializer (`+initialize`) is called in a fork child of a parent that has
multiple threads.
This appears to be due to calling `libintl_setlocale`, at `locale.c:369`, which
in turn calls `CFPreferencesCopyAppValue`, at `localename-unsafe.c:3406`, which
ultimately calling `dispatch_apply`, spawning long running threads.
After fork, `libintl_gettext` is called at `execute_cmd.c:5731`, which calls
`CFLocaleCopyPreferredLanguages` at `langprefs.c:253`, which (presumably)
attempts to initialize `__SwiftNativeNSStringBase`.
Back-trace of the first invocation (breaking on `dispatch_apply`):
```
* 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: 0x00000001005c7704 libintl.8.dylib`_libintl_locale_name_default
at localename-unsafe.c:3406:11 [opt]
frame #14: 0x00000001005c6734
libintl.8.dylib`libintl_setlocale(category=<unavailable>, locale=<unavailable>)
at setlocale.c:1446:25 [opt]
frame #15: 0x0000000100064df4 bash`reset_locale_vars at locale.c:369:7 [opt]
frame #16: 0x00000001000650ec bash`set_lang(var=<unavailable>,
value=<unavailable>) at locale.c:318:43 [opt] [artificial]
frame #17: 0x0000000100028314 bash`sv_locale(name="LANG") at
variables.c:6341:9 [opt]
frame #18: 0x000000010006ee74
bash`declare_internal(list=0x0000600000af7520, local_var=1) at
declare.def:1048:7 [opt]
frame #19: 0x000000010006f074 bash`local_builtin(list=<unavailable>) at
declare.def:134:13 [opt] [artificial]
frame #20: 0x000000010001f1b0 bash`execute_builtin_or_function [inlined]
execute_builtin(builtin=(bash`local_builtin at declare.def:125),
words=0x0000600000af7440, flags=<unavailable>, subshell=0) at
execute_cmd.c:4974:13 [opt]
frame #21: 0x000000010001eea4
bash`execute_builtin_or_function(words=0x0000600000af7440,
builtin=(bash`local_builtin at declare.def:125), var=0x0000000000000000,
redirects=<unavailable>, fds_to_close=<unavailable>, flags=<unavailable>) at
execute_cmd.c:5488:14 [opt]
frame #22: 0x000000010001a27c
bash`execute_simple_command(simple_command=<unavailable>,
pipe_in=<unavailable>, pipe_out=-1, async=<unavailable>,
fds_to_close=0x0000600000af7250) at execute_cmd.c:4740:13 [opt]
frame #23: 0x00000001000181a4
bash`execute_command_internal(command=0x00006000008daec0, asynchronous=0,
pipe_in=-1, pipe_out=-1, fds_to_close=0x0000600000af7250) at
execute_cmd.c:866:4 [opt]
frame #24: 0x00000001000174d0 bash`execute_command(command=<unavailable>)
at execute_cmd.c:413:12 [opt]
frame #25: 0x000000010001ba70
bash`execute_connection(command=0x00006000008dae80, asynchronous=0, pipe_in=-1,
pipe_out=-1, fds_to_close=0x0000600000af7230) at execute_cmd.c:2757:7 [opt]
frame #26: 0x0000000100017ff0
bash`execute_command_internal(command=0x00006000008dae80, asynchronous=0,
pipe_in=-1, pipe_out=-1, fds_to_close=0x0000600000af7230) at
execute_cmd.c:1040:21 [opt]
frame #27: 0x0000000100018244
bash`execute_command_internal(command=0x00006000008dae60, asynchronous=0,
pipe_in=-1, pipe_out=-1, fds_to_close=0x0000600000af7230) at execute_cmd.c:0
[opt]
frame #28: 0x000000010001bab0
bash`execute_connection(command=0x00006000008dade0, asynchronous=0, pipe_in=-1,
pipe_out=-1, fds_to_close=0x0000600000af7230) at execute_cmd.c:2766:21 [opt]
frame #29: 0x0000000100017ff0
bash`execute_command_internal(command=0x00006000008dade0, asynchronous=0,
pipe_in=-1, pipe_out=-1, fds_to_close=0x0000600000af7230) at
execute_cmd.c:1040:21 [opt]
frame #30: 0x00000001000174d0 bash`execute_command(command=<unavailable>)
at execute_cmd.c:413:12 [opt]
frame #31: 0x000000010001ba70
bash`execute_connection(command=0x00006000008dada0, asynchronous=0, pipe_in=-1,
pipe_out=-1, fds_to_close=0x0000600000af4de0) at execute_cmd.c:2757:7 [opt]
frame #32: 0x0000000100017ff0
bash`execute_command_internal(command=0x00006000008dada0, asynchronous=0,
pipe_in=-1, pipe_out=-1, fds_to_close=0x0000600000af4de0) at
execute_cmd.c:1040:21 [opt]
frame #33: 0x0000000100018244
bash`execute_command_internal(command=0x00006000008dad80, asynchronous=0,
pipe_in=-1, pipe_out=-1, fds_to_close=0x0000600000af4de0) at execute_cmd.c:0
[opt]
frame #34: 0x000000010001d744 bash`execute_function(var=0x00006000006ac570,
words=0x0000600000af67a0, flags=<unavailable>, fds_to_close=0x0000600000af4de0,
async=<unavailable>, subshell=0) at execute_cmd.c:5245:13 [opt]
frame #35: 0x000000010001ee9c
bash`execute_builtin_or_function(words=0x0000600000af67a0,
builtin=0x0000000000000000, var=0x00006000006ac570, redirects=<unavailable>,
fds_to_close=0x0000600000af4de0, flags=0) at execute_cmd.c:5490:14 [opt]
frame #36: 0x000000010001a580
bash`execute_simple_command(simple_command=<unavailable>,
pipe_in=<unavailable>, pipe_out=-1, async=<unavailable>,
fds_to_close=0x0000600000af4de0) at execute_cmd.c:4740:13 [opt]
frame #37: 0x00000001000181a4
bash`execute_command_internal(command=0x00006000008dabe0, asynchronous=0,
pipe_in=-1, pipe_out=-1, fds_to_close=0x0000600000af4de0) at
execute_cmd.c:866:4 [opt]
frame #38: 0x0000000100070f60 bash`parse_and_execute(string=<unavailable>,
from_file="PROMPT_COMMAND", flags=1029) at evalstring.c:539:17 [opt]
frame #39: 0x00000001000094b8
bash`execute_variable_command(command="update_terminal_cwd",
vname="PROMPT_COMMAND") at parse.y:2845:3 [opt]
frame #40: 0x00000001000066a0 bash`parse_command [inlined]
execute_prompt_command at eval.c:315:5 [opt]
frame #41: 0x0000000100006660 bash`parse_command at eval.c:341:9 [opt]
frame #42: 0x000000010000643c bash`read_command at eval.c:392:12 [opt]
frame #43: 0x00000001000061ec bash`reader_loop at eval.c:139:11 [opt]
frame #44: 0x0000000100004c94 bash`main(argc=2, argv=<unavailable>,
env=<unavailable>) at shell.c:833:3 [opt]
frame #45: 0x0000000182a6a0e0 dyld`start + 2360
```
Back-trace of the second:
```
thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
* frame #0: 0x0000000182dbf0ac libsystem_kernel.dylib`__abort_with_payload + 8
frame #1: 0x0000000182de4f08
libsystem_kernel.dylib`abort_with_payload_wrapper_internal + 104
frame #2: 0x0000000182de4ea0 libsystem_kernel.dylib`abort_with_reason + 32
frame #3: 0x0000000182a520f8 libobjc.A.dylib`_objc_fatalv(unsigned long
long, unsigned long long, char const*, char*) + 128
frame #4: 0x0000000182a52078 libobjc.A.dylib`_objc_fatal(char const*, ...)
+ 44
frame #5: 0x0000000182a38460
libobjc.A.dylib`performForkChildInitialize(objc_class*, objc_class*) + 400
frame #6: 0x0000000182a1eba4 libobjc.A.dylib`initializeNonMetaClass + 572
frame #7: 0x0000000182a1ea04 libobjc.A.dylib`initializeNonMetaClass + 156
frame #8: 0x0000000182a1ea04 libobjc.A.dylib`initializeNonMetaClass + 156
frame #9: 0x0000000182a3bbfc
libobjc.A.dylib`initializeAndMaybeRelock(objc_class*, objc_object*,
locker_mixin<lockdebug::lock_mixin<objc_lock_base_t>>&, bool) + 164
frame #10: 0x0000000182a1e5c4 libobjc.A.dylib`lookUpImpOrForward + 892
frame #11: 0x0000000182a1df64 libobjc.A.dylib`_objc_msgSend_uncached + 68
frame #12: 0x0000000192dfbbc8 libswiftCore.dylib`type metadata accessor for
Swift.__StringStorage + 24
frame #13: 0x0000000192b85f24
libswiftCore.dylib`Swift.String._bridgeToObjectiveCImpl() -> Swift.AnyObject +
152
frame #14: 0x0000000184409f80 Foundation`function signature specialization
<Arg[1] = Dead> of Foundation.LocaleCache.preferredLanguages(forCurrentUser:
Swift.Bool) -> Swift.Array<Swift.String> + 76
frame #15: 0x00000001844ec9c4 Foundation`@objc static
__C.NSLocale._preferredLanguagesForCurrentUser(Swift.Bool) ->
Swift.Array<Swift.String> + 44
frame #16: 0x0000000182ece0b4 CoreFoundation`CFLocaleCopyPreferredLanguages
+ 28
frame #17: 0x0000000101386174
libintl.8.dylib`_libintl_language_preferences_default at langprefs.c:253:32
[opt]
frame #18: 0x0000000101384ac8 libintl.8.dylib`libintl_dcigettext [inlined]
guess_category_value(category=6, categoryname="LC_MESSAGES") at
dcigettext.c:1643:26 [opt]
frame #19: 0x0000000101384a68
libintl.8.dylib`libintl_dcigettext(domainname="bash", msgid1="%s: command not
found", msgid2=0x0000000000000000, plural=0, n=0, category=<unavailable>) at
dcigettext.c:710:19 [opt]
frame #20: 0x0000000101382338
libintl.8.dylib`libintl_dcgettext(domainname=<unavailable>,
msgid=<unavailable>, category=<unavailable>) at dcgettext.c:47:10 [opt]
[artificial]
frame #21: 0x0000000101382350
libintl.8.dylib`libintl_gettext(msgid=<unavailable>) at gettext.c:55:10 [opt]
[artificial]
frame #22: 0x0000000100ddf658
bash`execute_disk_command(words=0x00006000029e8e70,
redirects=0x0000000000000000, command_line="derp", pipe_in=<unavailable>,
pipe_out=<unavailable>, async=<unavailable>, fds_to_close=0x000060000298c040,
cmdflags=0) at execute_cmd.c:5731:24 [opt]
frame #23: 0x0000000100dda378
bash`execute_simple_command(simple_command=<unavailable>, pipe_in=-1,
pipe_out=-1, async=<unavailable>, fds_to_close=0x000060000298c040) at
execute_cmd.c:4814:12 [opt]
frame #24: 0x0000000100dd8188
bash`execute_command_internal(command=0x0000600002b800a0, asynchronous=0,
pipe_in=-1, pipe_out=-1, fds_to_close=0x000060000298c040) at
execute_cmd.c:866:4 [opt]
frame #25: 0x0000000100dd74b4 bash`execute_command(command=<unavailable>)
at execute_cmd.c:413:12 [opt]
frame #26: 0x0000000100dc62c4 bash`reader_loop at eval.c:171:8 [opt]
frame #27: 0x0000000100dc4c78 bash`main(argc=2, argv=<unavailable>,
env=<unavailable>) at shell.c:833:3 [opt]
frame #28: 0x0000000182a6a0e0 dyld`start + 2360
```
Repeat-By:
```
#!/usr/bin/env bash
set -eu
fetch_gettext () {
wget --continue
https://mirror.endianness.com/gnu/gettext/gettext-0.22.5.tar.gz
}
fetch_bash () {
wget --continue https://mirror.endianness.com/gnu/bash/bash-5.2.tar.gz
mkdir -p bash-5.2-patches
pushd bash-5.2-patches
for i in $(seq -w 01 26)
do
wget --continue
https://mirror.endianness.com/gnu/bash/bash-5.2-patches/bash52-0${i}
done
popd
}
fetch () {
mkdir -p assets
pushd assets
fetch_gettext
fetch_bash
popd
}
build_gettext () {
prefix=${1}
tar -xzf ../assets/gettext-0.22.5.tar.gz
pushd gettext-0.22.5/gettext-runtime
./configure --prefix=${prefix} --silent
make --jobs 12 --silent install
popd
}
build_bash () {
prefix=${1}
tar -xzf ../assets/bash-5.2.tar.gz
pushd bash-5.2
for i in $(seq -w 01 26)
do
patch -p0 < ../../assets/bash-5.2-patches/bash52-0${i}
done
LDFLAGS=-L${prefix}/lib ./configure --silent
make --jobs 12 --silent
popd
}
build () {
prefix=$(mktemp -d)
rm -rf build
mkdir build
pushd build
build_gettext ${prefix}
build_bash ${prefix}
popd
}
fetch
build
./build/bash-5.2/bash -l # execute invalid command
```
Regards,
Tom Sullivan
Head Developer
Most Significant Bit Software
e: tom@msbit.com.au
p: +61 407 890 821
- macOS 14 objc `+initialize` forced crash due to fork after thread,
Tom <=