`getaddrinfo()` in forked child crashes in _os_log_preferences_refresh on macOS 26 Tahoe for IPv4-only hosts (FB21364061)

Since macOS 26 (Tahoe), getaddrinfo() with AF_UNSPEC for a hostname whose DNS answer contains only A records (no AAAA) fails in forked child processes when the parent performed DNS resolution, or otherwise initialized os_log, before forking. This is a regression: the same code works on macOS 15.x and earlier.

The child crashes with EXC_BAD_ACCESS (KERN_INVALID_ADDRESS) inside the NAT64 synthesis path:

_os_log_preferences_refresh        (libsystem_trace.dylib)   <- faulting frame
os_log_type_enabled                (libsystem_trace.dylib)
nw_path_access_agent_cache         (Network)
_nw_path_update_is_viableTm / nw_path_snapshot_path / nw_path_evaluator_evaluate
nw_nat64_v4_address_requires_synthesis
_gai_nat64_second_pass             (libsystem_info.dylib)
si_addrinfo -> getaddrinfo

Runtimes that install a SIGSEGV handler (Ruby, Python) do not die; instead the DNS helper thread spins at 100% CPU and the process hangs. We have also captured a parent-side variant where a later fork() deadlocks in the atfork prepare path itself: libSystem_atfork_prepare -> nw_path_prepare_fork -> _os_unfair_lock_lock_slow.

Minimal trigger in C:

os_log_t log = os_log_create("com.example.repro", "repro");
os_log(log, "init");

struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }, *res;
getaddrinfo("api.stripe.com", "443", &hints, &res);   // parent: IPv4-only host

if (fork() == 0) {
    getaddrinfo("api.stripe.com", "443", &hints, &res); // child: crashes in _os_log_preferences_refresh
    _exit(0);
}

Observed behavior and boundaries:

Reproduces on 26.1 through 26.5.1 (25F80). Not reproducible on macOS 15.x.

Only AF_UNSPEC lookups of IPv4-only hostnames are affected. AF_INET hints, IPv6-capable hostnames (for example google.com), numeric literals, and localhost are all immune. AF_INET6-only lookups neither trigger nor prevent it.

The failure is all-or-nothing per parent process: once a parent is in the affected state, every forked child fails. On 26.5.1 it reproduces most reliably when the process was exec'd over a prior os_log-using image (for example Ruby launched via bundle exec, where the bundler Ruby execs the target Ruby in the same process), and intermittently from a bare shell. On 26.1 even bare runs reproduced readily. This is consistent with per-process logging state surviving exec and then being inherited invalid across fork.

I understand that officially only async-signal-safe calls are supported between fork and exec. But this worked through macOS 15, and it breaks the pre-forking worker model used by major Ruby and Python frameworks (Resque, Unicorn, multiprocessing) on developer machines.

Filed as FB21364061 in December 2025, no response so far. Is this a known issue, and is a fix present or planned in macOS 26.6 or the macOS 27 beta?

Answered by DTS Engineer in 894187022

I don’t have any good news for you here )-:

As you’re aware, the runtime environment you get when you call fork but not exec* is extremely restricted, and calling getaddrinfo is not something we officially support. And when you do unsupported things, you run the risk of all sorts of odd compatibility problems. Filing a compatibility bug is reasonable, but we don’t always fix those. It kinda depends on the overall compatibility impact.

Filed as FB21364061

Thanks for that. Your bug is still open, rather than being returned as ‘not to be fixed’, but I wouldn’t read too much into that. The fact that this has been around for almost a complete major OS releases cycle, and isn’t fixed in macOS 27 beta, is telling. If your have a product that’s having this problem, you should you plan to resolve that by fixing your code. And if your primary concern is others folks’ products — like the open source worker mechanisms you mentioned in your bug — you should raise this situation with those products’ vendors.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

I don’t have any good news for you here )-:

As you’re aware, the runtime environment you get when you call fork but not exec* is extremely restricted, and calling getaddrinfo is not something we officially support. And when you do unsupported things, you run the risk of all sorts of odd compatibility problems. Filing a compatibility bug is reasonable, but we don’t always fix those. It kinda depends on the overall compatibility impact.

Filed as FB21364061

Thanks for that. Your bug is still open, rather than being returned as ‘not to be fixed’, but I wouldn’t read too much into that. The fact that this has been around for almost a complete major OS releases cycle, and isn’t fixed in macOS 27 beta, is telling. If your have a product that’s having this problem, you should you plan to resolve that by fixing your code. And if your primary concern is others folks’ products — like the open source worker mechanisms you mentioned in your bug — you should raise this situation with those products’ vendors.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

&#96;getaddrinfo()&#96; in forked child crashes in _os_log_preferences_refresh on macOS 26 Tahoe for IPv4-only hosts (FB21364061)
 
 
Q