From 8105307f0f3caeae1c1d0bca51bee3a417e4304a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikodem=20Rabuli=C5=84ski?= Date: Mon, 6 May 2024 18:16:50 +0200 Subject: [PATCH] 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] https://github.com/apple-oss-distributions/objc4/blob/01edf1705fbc3ff78a423cd21e03dfc21eb4d780/runtime/objc-initialize.mm#L614-L636 (cherry-picked and adapted from https://git.lix.systems/lix-project/lix/commit/c7d97802e4f59b8621e67cf62275d6a7fde8fe62) --- misc/launchd/org.nixos.nix-daemon.plist.in | 5 ----- package.nix | 5 ----- src/libstore/globals.cc | 14 +++++++++++++- tests/functional/package.nix | 7 ------- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/misc/launchd/org.nixos.nix-daemon.plist.in b/misc/launchd/org.nixos.nix-daemon.plist.in index e1470cf99..664608305 100644 --- a/misc/launchd/org.nixos.nix-daemon.plist.in +++ b/misc/launchd/org.nixos.nix-daemon.plist.in @@ -2,11 +2,6 @@ - EnvironmentVariables - - OBJC_DISABLE_INITIALIZE_FORK_SAFETY - YES - Label org.nixos.nix-daemon KeepAlive diff --git a/package.nix b/package.nix index 5c8d9f9b6..8ab184667 100644 --- a/package.nix +++ b/package.nix @@ -325,11 +325,6 @@ in { preInstallCheck = lib.optionalString (! doBuild) '' 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; diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 8958e6997..b64e73c26 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -12,6 +12,7 @@ #include #include +#include #include #ifndef _WIN32 @@ -363,10 +364,21 @@ void initLibStore(bool loadConfig) { 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 sshd). This breaks build users because they don't have access to the TMPDIR, in particular in ‘nix-store --serve’. */ -#if __APPLE__ if (hasPrefix(defaultTempDir(), "/var/folders/")) unsetenv("TMPDIR"); #endif diff --git a/tests/functional/package.nix b/tests/functional/package.nix index 277711123..675cefa64 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -95,13 +95,6 @@ mkMesonDerivation (finalAttrs: { "--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; installPhase = ''