Always initialize curl in parent process on darwin

Because of an objc quirk[1], calling curl_global_init for the first time
after fork() will always result in a crash.
Up until now the solution has been to set
OBJC_DISABLE_INITIALIZE_FORK_SAFETY for every nix process to ignore
that error.
This is less than ideal because we were setting it in package.nix,
which meant that running nix tests locally would fail because
that variable was not set.
Instead of working around that error we address it at the core -
by calling curl_global_init inside initLibStore, which should mean
curl will already have been initialized by the time we try to do so in
a forked process.

[1] 01edf1705f/runtime/objc-initialize.mm (L614-L636)

(cherry-picked and adapted from c7d97802e4)
This commit is contained in:
Nikodem Rabuliński 2024-05-06 18:16:50 +02:00 committed by Jörg Thalheim
parent a20659f4fa
commit 8105307f0f
4 changed files with 13 additions and 18 deletions

View File

@ -2,11 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>EnvironmentVariables</key>
<dict>
<key>OBJC_DISABLE_INITIALIZE_FORK_SAFETY</key>
<string>YES</string>
</dict>
<key>Label</key> <key>Label</key>
<string>org.nixos.nix-daemon</string> <string>org.nixos.nix-daemon</string>
<key>KeepAlive</key> <key>KeepAlive</key>

View File

@ -325,11 +325,6 @@ in {
preInstallCheck = preInstallCheck =
lib.optionalString (! doBuild) '' lib.optionalString (! doBuild) ''
mkdir -p src/nix-channel mkdir -p src/nix-channel
''
# See https://github.com/NixOS/nix/issues/2523
# Occurs often in tests since https://github.com/NixOS/nix/pull/9900
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
''; '';
separateDebugInfo = !stdenv.hostPlatform.isStatic; separateDebugInfo = !stdenv.hostPlatform.isStatic;

View File

@ -12,6 +12,7 @@
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <curl/curl.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#ifndef _WIN32 #ifndef _WIN32
@ -363,10 +364,21 @@ void initLibStore(bool loadConfig) {
preloadNSS(); preloadNSS();
/* Because of an objc quirk[1], calling curl_global_init for the first time
after fork() will always result in a crash.
Up until now the solution has been to set OBJC_DISABLE_INITIALIZE_FORK_SAFETY
for every nix process to ignore that error.
Instead of working around that error we address it at the core -
by calling curl_global_init here, which should mean curl will already
have been initialized by the time we try to do so in a forked process.
[1] https://github.com/apple-oss-distributions/objc4/blob/01edf1705fbc3ff78a423cd21e03dfc21eb4d780/runtime/objc-initialize.mm#L614-L636
*/
curl_global_init(CURL_GLOBAL_ALL);
#if __APPLE__
/* On macOS, don't use the per-session TMPDIR (as set e.g. by /* On macOS, don't use the per-session TMPDIR (as set e.g. by
sshd). This breaks build users because they don't have access sshd). This breaks build users because they don't have access
to the TMPDIR, in particular in nix-store --serve. */ to the TMPDIR, in particular in nix-store --serve. */
#if __APPLE__
if (hasPrefix(defaultTempDir(), "/var/folders/")) if (hasPrefix(defaultTempDir(), "/var/folders/"))
unsetenv("TMPDIR"); unsetenv("TMPDIR");
#endif #endif

View File

@ -95,13 +95,6 @@ mkMesonDerivation (finalAttrs: {
"--print-errorlogs" "--print-errorlogs"
]; ];
preCheck =
# See https://github.com/NixOS/nix/issues/2523
# Occurs often in tests since https://github.com/NixOS/nix/pull/9900
lib.optionalString stdenv.hostPlatform.isDarwin ''
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
'';
doCheck = true; doCheck = true;
installPhase = '' installPhase = ''