packages feed

hercules-ci-cnix-store 0.3.7.0 → 0.4.0.0

raw patch · 12 files changed

+152/−573 lines, 12 files

Files

CHANGELOG.md view
@@ -5,6 +5,13 @@  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## 0.4.0.0 - 2025-07-18++### Changed++ - `init` now installs synchronous signal handlers for you. You may remove your call to `installDefaultSigINTHandler`.+ - The `nix-main` library dependency has been dropped. (if you don't also use `hercules-ci-cnix-expr`)+ ## 0.3.7.0 - 2025-05-05  ### Added
+ cbits/signals.cxx view
@@ -0,0 +1,65 @@+#include <csignal>+#include <unistd.h>++#include <nix/util/signals.hh>++#include "signals.hxx"++extern "C" {++// Storage for previous signal handlers+static struct sigaction old_sigint_action;+static struct sigaction old_sigterm_action;+static struct sigaction old_sighup_action;++// Get pointer to the old action structure for a given signal+static struct sigaction* get_old_action(int sig) {+    switch (sig) {+        case SIGINT: return &old_sigint_action;+        case SIGTERM: return &old_sigterm_action;+        case SIGHUP: return &old_sighup_action;+        default: return nullptr;+    }+}++// C signal handler that runs immediately in signal context+// This calls nix::triggerInterrupt() synchronously then defers to the previous handler+static void hercules_nix_signal_handler(int sig) {+    // Set the Nix interrupt flag immediately+    // This ensures checkInterrupt() calls after EINTR will work correctly+    nix::unix::triggerInterrupt();+    +    // Call the previous handler to preserve existing behavior+    struct sigaction* old_action = get_old_action(sig);+    if (old_action && old_action->sa_handler != SIG_DFL && old_action->sa_handler != SIG_IGN) {+        if (old_action->sa_flags & SA_SIGINFO) {+            // Previous handler expects siginfo_t+            // We can't call it properly without the siginfo, so just call the basic handler+            if (old_action->sa_handler) {+                old_action->sa_handler(sig);+            }+        } else {+            // Previous handler is a simple function pointer+            old_action->sa_handler(sig);+        }+    }+}++// Install our C signal handler for the given signal, chaining to the previous handler+// Returns 0 on success, -1 on error+int hercules_install_signal_handler(int sig) {+    struct sigaction new_action;+    new_action.sa_handler = hercules_nix_signal_handler;+    sigemptyset(&new_action.sa_mask);+    new_action.sa_flags = 0;  // Ensure SA_RESTART is not set+    +    struct sigaction* old_action = get_old_action(sig);+    if (!old_action) {+        return -1;  // Unknown signal+    }+    +    // Install new handler and save the old one+    return sigaction(sig, &new_action, old_action);+}++} // extern "C"
+ cbits/signals.hxx view
@@ -0,0 +1,17 @@+#ifndef HERCULES_SIGNALS_H+#define HERCULES_SIGNALS_H++#ifdef __cplusplus+extern "C" {+#endif++// Install our C signal handler for the given signal+// This handler calls nix::triggerInterrupt() synchronously+// Returns 0 on success, -1 on error+int hercules_install_signal_handler(int sig);++#ifdef __cplusplus+}+#endif++#endif // HERCULES_SIGNALS_H
hercules-ci-cnix-store.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4  name:           hercules-ci-cnix-store-version:        0.3.7.0+version:        0.4.0.0 synopsis:       Haskell bindings for Nix's libstore category:       Nix homepage:       https://docs.hercules-ci.com@@ -19,27 +19,15 @@   type: git   location: https://github.com/hercules-ci/hercules-ci-agent --- Deprecated-flag nix-2_4-  description: Build for Nix >=2.4pre*-  default: True -flag nix-2_15-  description: Build for Nix >=2.15.0-  default: False- flag ide   description: Whether to enable IDE workarounds. You shouldn't need this.   default: False  -- match the C++ language standard Nix is using common cxx-opts-  if flag(nix-2_15)-    cxx-options:-      -std=c++2a-  else-    cxx-options:-      -std=c++17+  cxx-options:+    -std=c++2a    cxx-options:     -Wall@@ -54,16 +42,11 @@   if impl(ghc >= 8.10)     ghc-options:       -optcxx-Wall-    if flag(nix-2_15)-      ghc-options:-        -optcxx-std=c++2a-    else-      ghc-options:-        -optcxx-std=c++17+      -optcxx-std=c++2a   else     -- Remove soon     ghc-options:-      -optc-std=c++17+      -optc-std=c++2a       -optc-Wall     if os(darwin)       ghc-options: -pgmc=clang++@@ -94,15 +77,17 @@       Hercules.CNix.Verbosity   include-dirs:       include+      cbits   pkgconfig-depends:-      nix-store (>= 2.4 && < 2.19) || (>= 2.19.3 && < 2.21) || (>= 2.24.10 && < 2.25) || (>= 2.28 && < 2.29)-    , nix-main >= 2.4 && < 2.19 || (>= 2.19.3 && < 2.21) || (>= 2.24.10 && < 2.25) || (>= 2.28 && < 2.29)+      nix-store >= 2.28 && < 2.29   install-includes:       hercules-ci-cnix/store.hxx       hercules-ci-cnix/string.hxx   hs-source-dirs: src   cxx-sources:       cbits/string.cxx+      cbits/signals.cxx+      cbits/signals.hxx   build-depends:       base >= 4.7 && <5     , inline-c
include/hercules-ci-cnix/store.hxx view
@@ -1,11 +1,7 @@  #pragma once -#if NIX_IS_AT_LEAST(2,28,0) #include <nix/store/path-info.hh>-#else-#include <nix/path-info.hh>-#endif  typedef nix::ref<nix::Store> refStore; @@ -15,8 +11,4 @@ typedef nix::PathSet::iterator PathSetIterator; typedef nix::ref<const nix::ValidPathInfo> refValidPathInfo; -#if NIX_IS_AT_LEAST(2,18,0) typedef nix::DerivedPathMap<std::set<nix::OutputName>>::Map::iterator DerivationInputsIterator;-#else-typedef nix::DerivationInputs::iterator DerivationInputsIterator;-#endif
src/Hercules/CNix.hs view
@@ -23,6 +23,7 @@  import Data.ByteString.Unsafe (unsafePackMallocCString) import Hercules.CNix.Store+import qualified Hercules.CNix.Util import Hercules.CNix.Verbosity   ( Verbosity (Debug, Talkative),     setVerbosity,@@ -34,28 +35,11 @@  C.context context -#if NIX_IS_AT_LEAST(2, 28, 0)- C.include "<nix/util/config-global.hh>" C.include "<nix/store/derivations.hh>" C.include "<nix/store/globals.hh>" C.include "<nix/main/shared.hh>" -#else-C.include "<stdio.h>"-C.include "<cstring>"-C.include "<math.h>"-C.include "<nix/config.h>"-C.include "<nix/shared.hh>"-C.include "<nix/store-api.hh>"-C.include "<nix/get-drvs.hh>"-C.include "<nix/derivations.hh>"-C.include "<nix/globals.hh>"-#  if NIX_IS_AT_LEAST(2, 24, 0)-C.include "<config-global.hh>"-#  endif-#endif- C.include "<gc/gc.h>" C.include "<gc/gc_cpp.h>" C.include "<gc/gc_allocator.h>"@@ -66,12 +50,16 @@ C.using "namespace nix" C.using "namespace hercules_ci_cnix" +-- | Initialize the Nix store library. If you also use the Nix evaluator, you should+-- call 'Hercules.CNix.Expr.init' instead. init :: IO ()-init =+init = do   void     [C.throwBlock| void {-      nix::initNix();+      nix::initLibStore();     } |]+  -- Install signal handlers using Haskell primitives (replaces nix::unix::startSignalHandlerThread)+  Hercules.CNix.Util.installDefaultSigINTHandler  setTalkative :: IO () setTalkative = setVerbosity Talkative
src/Hercules/CNix/Exception.hs view
@@ -17,15 +17,13 @@  C.context context -#if NIX_IS_AT_LEAST(2, 28, 0)-C.include "<nix/main/shared.hh>" C.include "<nix/store/globals.hh>"-#else-C.include "<nix/config.h>"-C.include "<nix/shared.hh>"-C.include "<nix/globals.hh>"-#endif+C.include "<nix/util/logging.hh>"+C.include "<nix/util/signals.hh>"+C.include "<nix/util/error.hh>" +C.using "namespace nix"+ -- | Log C++ exceptions and call 'exitWith' the way Nix would exit when an -- exception occurs. handleExceptions :: IO a -> IO a@@ -57,7 +55,29 @@   [C.throwBlock| int {     auto & eptr = *$fptr-ptr:(std::exception_ptr *eptr);     std::string programName($bs-ptr:programName, $bs-len:programName);-    return nix::handleExceptions(programName, [&]() {-      std::rethrow_exception(eptr);-    });+    // Based on nix::handleExceptions, but without the libmain-specific stuff+    std::string error = ANSI_RED "error:" ANSI_NORMAL " ";+    try {+      try {+        try {+          std::rethrow_exception(eptr);+        } catch (...) {+          // Avoid throwing another interrupt error in the print routines that actually catch this.+          setInterruptThrown();+          throw;+        }+      } catch (BaseError & e) {+          logError(e.info());+          return e.info().status;+      } catch (std::bad_alloc & e) {+          printError(error + "out of memory");+          return 1;+      } catch (std::exception & e) {+          printError(error + e.what());+          return 1;+      }+    } catch (...) {+      // Nix would exit with 1, but this is a truly exceptional error, so we return -1+      return -1;+    }   }|]
src/Hercules/CNix/Settings.hs view
@@ -40,12 +40,7 @@ C.include "<set>" C.include "<string>" -#if NIX_IS_AT_LEAST(2, 28, 0) C.include "<nix/store/globals.hh>"-#else-C.include "<nix/config.h>"-C.include "<nix/globals.hh>"-#endif  C.include "hercules-ci-cnix/string.hxx" 
src/Hercules/CNix/Store.hs view
@@ -189,9 +189,6 @@  C.include "<variant>" -#if NIX_IS_AT_LEAST(2, 28, 0)--C.include "<nix/main/shared.hh>" C.include "<nix/store/store-api.hh>" C.include "<nix/store/derivations.hh>" C.include "<nix/store/globals.hh>"@@ -200,43 +197,6 @@ C.include "<nix/store/path-with-outputs.hh>" C.include "<nix/util/signals.hh>" -#else--C.include "<nix/config.h>"--C.include "<nix/shared.hh>"--C.include "<nix/store-api.hh>"--C.include "<nix/get-drvs.hh>"--C.include "<nix/derivations.hh>"--C.include "<nix/globals.hh>"--C.include "<nix/path.hh>"--C.include "<nix/worker-protocol.hh>"--C.include "<nix/path-with-outputs.hh>"--C.include "<nix/hash.hh>"--#  if NIX_IS_AT_LEAST(2,19,0)--C.include "<nix/signals.hh>"--C.include "<nix/hash.hh>"--#  endif--#  if ! NIX_IS_AT_LEAST(2,20,0)--C.include "<nix/nar-info-disk-cache.hh>"--#  endif-#endif- C.include "hercules-ci-cnix/store.hxx"  C.include "hercules-ci-cnix/string.hxx"@@ -604,7 +564,6 @@   deriving (Eq, Show)  getDerivationOutputs :: Store -> ByteString -> Derivation -> IO [DerivationOutput]-#if NIX_IS_AT_LEAST(2, 24, 0) getDerivationOutputs (Store store) drvName (Derivation derivationFPtr) =   withForeignPtr derivationFPtr \derivation ->   withDelete@@ -775,357 +734,7 @@                     )           )             <*> continue-#else--- < 2.24-getDerivationOutputs (Store store) drvName (Derivation derivationFPtr) =-  withForeignPtr derivationFPtr \derivation ->-  withDelete-    [C.exp| DerivationOutputsIterator* {-      new DerivationOutputsIterator($(Derivation *derivation)->outputs.begin())-    }|] \i ->-    fix $ \continue -> do-      isEnd <- (0 /=) <$> [C.exp| bool { *$(DerivationOutputsIterator *i) == $(Derivation *derivation)->outputs.end() }|]-      if isEnd-        then pure []-        else-          ( mask_ do-              alloca \nameP -> alloca \pathP -> alloca \typP -> alloca \fimP ->-                alloca \hashTypeP -> alloca \hashValueP -> alloca \hashSizeP -> do-                  [C.throwBlock| void {-                    Store &store = **$(refStore *store);-                    std::string drvName = std::string($bs-ptr:drvName, $bs-len:drvName);-                    nix::DerivationOutputs::iterator &i = *$(DerivationOutputsIterator *i);-                    const char *&name = *$(const char **nameP);-                    int &typ = *$(int *typP);-                    StorePath *& path = *$(nix::StorePath **pathP);-                    int &fim = *$(int *fimP);-                    int &hashType = *$(int *hashTypeP);-                    char *&hashValue = *$(char **hashValueP);-                    int &hashSize = *$(int *hashSizeP); -                    std::string nameString = i->first;-                    name = stringdup(nameString);-                    path = nullptr;-                    std::visit(overloaded {-#if NIX_IS_AT_LEAST(2, 18, 0)-                      [&](DerivationOutput::InputAddressed doi) -> void {-                        typ = 0;-                        path = new StorePath(doi.path);-                      },-                      [&](DerivationOutput::CAFixed dof) -> void {-                        typ = 1;-                        path = new StorePath(dof.path(store, $(Derivation *derivation)->name, nameString));-                        std::visit(overloaded {-                          [&](nix::FileIngestionMethod fim_) -> void {-                            switch (fim_) {-                              case nix::FileIngestionMethod::Flat:-                                fim = 0;-                                break;-                              case nix::FileIngestionMethod::Recursive:-                                fim = 1;-                                break;-                              default:-                                fim = -1;-                                break;-                            }-                          },-                          [&](nix::TextIngestionMethod) -> void {-                            // FIXME (RFC 92)-                            fim = -1;-                          }-                        }, dof.ca.method.raw);--                        const Hash & hash = dof.ca.hash;--#if NIX_IS_AT_LEAST(2, 20, 0)-                        switch (hash.algo) {-                          case HashAlgorithm::MD5:-                            hashType = 0;-                            break;-                          case HashAlgorithm::SHA1:-                            hashType = 1;-                            break;-                          case HashAlgorithm::SHA256:-                            hashType = 2;-                            break;-                          case HashAlgorithm::SHA512:-                            hashType = 3;-                            break;-#else-                        switch (hash.type) {-                          case htMD5:-                            hashType = 0;-                            break;-                          case htSHA1:-                            hashType = 1;-                            break;-                          case htSHA256:-                            hashType = 2;-                            break;-                          case htSHA512:-                            hashType = 3;-                            break;-#endif-                          default:-                            hashType = -1;-                            break;-                        }-                        hashSize = hash.hashSize;-                        hashValue = (char*)malloc(hashSize);-                        std::memcpy((void*)(hashValue),-                                    (void*)(hash.hash),-                                    hashSize);-                      },-                      [&](DerivationOutput::CAFloating dof) -> void {-                        typ = 2;-                        std::visit(overloaded {-                          [&](nix::FileIngestionMethod fim_) -> void {-                            switch (fim_) {-                              case nix::FileIngestionMethod::Flat:-                                fim = 0;-                                break;-                              case nix::FileIngestionMethod::Recursive:-                                fim = 1;-                                break;-                              default:-                                fim = -1;-                                break;-                            }-                          },-                          [&](nix::TextIngestionMethod) -> void {-                            // FIXME (RFC 92)-                            fim = -1;-                          }-                        }, dof.method.raw);-#if NIX_IS_AT_LEAST(2, 20, 0)-                        switch (dof.hashAlgo) {-                          case HashAlgorithm::MD5:-                            hashType = 0;-                            break;-                          case HashAlgorithm::SHA1:-                            hashType = 1;-                            break;-                          case HashAlgorithm::SHA256:-                            hashType = 2;-                            break;-                          case HashAlgorithm::SHA512:-                            hashType = 3;-                            break;-#else-                        switch (dof.hashType) {-                          case htMD5:-                            hashType = 0;-                            break;-                          case htSHA1:-                            hashType = 1;-                            break;-                          case htSHA256:-                            hashType = 2;-                            break;-                          case htSHA512:-                            hashType = 3;-                            break;-#endif-                          default:-                            hashType = -1;-                            break;-                        }-                      },-                      [&](DerivationOutput::Deferred) -> void {-                        typ = 3;-                      },-                      [&](DerivationOutput::Impure) -> void {-                        typ = 4;-                      },-                    },-                    i->second.raw-#else-                      [&](DerivationOutputInputAddressed doi) -> void {-                        typ = 0;-                        path = new StorePath(doi.path);-                      },-                      [&](DerivationOutputCAFixed dof) -> void {-                        typ = 1;-                        path = new StorePath(dof.path(store, $(Derivation *derivation)->name, nameString));-#if NIX_IS_AT_LEAST(2, 16, 0)-                        std::visit(overloaded {-                          [&](nix::FileIngestionMethod fim_) -> void {-                            switch (fim_) {-                              case nix::FileIngestionMethod::Flat:-                                fim = 0;-                                break;-                              case nix::FileIngestionMethod::Recursive:-                                fim = 1;-                                break;-                              default:-                                fim = -1;-                                break;-                            }-                          },-                          [&](nix::TextIngestionMethod) -> void {-                            // FIXME (RFC 92)-                            fim = -1;-                          }-#  if NIX_IS_AT_LEAST(2, 17, 0)-                        }, dof.ca.method.raw);-#  else-                        }, dof.ca.getMethod().raw);-#  endif-#else-                        switch (dof.hash.method) {-                          case nix::FileIngestionMethod::Flat:-                            fim = 0;-                            break;-                          case nix::FileIngestionMethod::Recursive:-                            fim = 1;-                            break;-                          default:-                            fim = -1;-                            break;-                        }-#endif--#if NIX_IS_AT_LEAST(2, 17, 0)-                        const Hash & hash = dof.ca.hash;-#elif NIX_IS_AT_LEAST(2, 16, 0)-                        const Hash & hash = dof.ca.getHash();-#else-                        const Hash & hash = dof.hash.hash;-#endif-                        switch (hash.type) {-                          case htMD5: -                            hashType = 0;-                            break;-                          case htSHA1: -                            hashType = 1;-                            break;-                          case htSHA256: -                            hashType = 2;-                            break;-                          case htSHA512: -                            hashType = 3;-                            break;-                          default:-                            hashType = -1;-                            break;-                        }-                        hashSize = hash.hashSize;-                        hashValue = (char*)malloc(hashSize);-                        std::memcpy((void*)(hashValue),-                                    (void*)(hash.hash),-                                    hashSize);-                      },-                      [&](DerivationOutputCAFloating dof) -> void {-                        typ = 2;-#if NIX_IS_AT_LEAST(2, 16, 0)-                        std::visit(overloaded {-                          [&](nix::FileIngestionMethod fim_) -> void {-                            switch (fim_) {-                              case nix::FileIngestionMethod::Flat:-                                fim = 0;-                                break;-                              case nix::FileIngestionMethod::Recursive:-                                fim = 1;-                                break;-                              default:-                                fim = -1;-                                break;-                            }-                          },-                          [&](nix::TextIngestionMethod) -> void {-                            // FIXME (RFC 92)-                            fim = -1;-                          }-                        }, dof.method.raw);-#else-                        switch (dof.method) {-                          case nix::FileIngestionMethod::Flat:-                            fim = 0;-                            break;-                          case nix::FileIngestionMethod::Recursive:-                            fim = 1;-                            break;-                          default:-                            fim = -1;-                            break;-                        }-#endif-                        switch (dof.hashType) {-                          case htMD5: -                            hashType = 0;-                            break;-                          case htSHA1: -                            hashType = 1;-                            break;-                          case htSHA256: -                            hashType = 2;-                            break;-                          case htSHA512: -                            hashType = 3;-                            break;-                          default:-                            hashType = -1;-                            break;-                        }-                      },-                      [&](DerivationOutputDeferred) -> void {-                        typ = 3;-                      },-#if NIX_IS_AT_LEAST(2,8,0)-                      [&](DerivationOutputImpure) -> void {-                        typ = 4;-                      },-#endif-                    },-#if NIX_IS_AT_LEAST(2,8,0)-                      i->second.raw()-#else-                      i->second.output-#endif-#endif-                    );-                    i++;-                  }|]-                  name <- unsafePackMallocCString =<< peek nameP-                  path <- nullableMoveToForeignPtrWrapper =<< peek pathP-                  typ <- peek typP-                  let getFileIngestionMethod = peek fimP <&> \case 0 -> Flat; 1 -> Recursive; _ -> panic "getDerivationOutputs: unknown fim"-                      getHashType =-                        peek hashTypeP <&> \case-                          0 -> MD5-                          1 -> SHA1-                          2 -> SHA256-                          3 -> SHA512-                          _ -> panic "getDerivationOutputs: unknown hashType"-                  detail <- case typ of-                    0 -> pure $ DerivationOutputInputAddressed (fromMaybe (panic "getDerivationOutputs: impossible DOIA path missing") path)-                    1 -> do-                      hashValue <- peek hashValueP-                      hashSize <- peek hashSizeP-                      hashString <- SBS.packCStringLen (hashValue, fromIntegral hashSize)-                      free hashValue-                      hashType <- getHashType-                      fim <- getFileIngestionMethod-                      pure $ DerivationOutputCAFixed (FixedOutputHash fim (Hash hashType hashString)) (fromMaybe (panic "getDerivationOutputs: impossible DOCF path missing") path)-                    2 -> do-                      hashType <- getHashType-                      fim <- getFileIngestionMethod-                      pure $ DerivationOutputCAFloating fim hashType-                    3 -> pure DerivationOutputDeferred-                    4 -> panic "getDerivationOutputs: impure derivations not supported yet"-                    _ -> panic "getDerivationOutputs: impossible getDerivationOutputs typ"-                  pure-                    ( DerivationOutput-                        { derivationOutputName = name,-                          derivationOutputPath = path,-                          derivationOutputDetail = detail-                        }-                        :-                    )-          )-            <*> continue-#endif- instance Delete DerivationOutputsIterator where   delete a = [C.block| void { delete $(DerivationOutputsIterator *a); }|] @@ -1179,7 +788,6 @@  -- | Get the inputs of a derivation, ignoring dependencies on outputs of outputs (RFC 92 inputs). getDerivationInputs' :: Derivation -> IO [(StorePath, [ByteString])]-#if NIX_IS_AT_LEAST(2, 18, 0) getDerivationInputs' (Derivation derivationFPtr) =   withForeignPtr derivationFPtr \derivation ->   withDelete@@ -1214,36 +822,6 @@               toByteStrings           [C.block| void { (*$(DerivationInputsIterator *i))++; }|]           ((name, outs) :) <$> continue-#else-getDerivationInputs' (Derivation derivationFPtr) =-  withForeignPtr derivationFPtr \derivation ->-  withDelete-    [C.exp| DerivationInputsIterator* {-      new DerivationInputsIterator($(Derivation *derivation)->inputDrvs.begin())-    }|]-    $ \i -> fix $ \continue -> do-      isEnd <- (0 /=) <$> [C.exp| bool { *$(DerivationInputsIterator *i) == $(Derivation *derivation)->inputDrvs.end() }|]-      if isEnd-        then pure []-        else do-          name <--            [C.throwBlock| nix::StorePath *{-              return new StorePath((*$(DerivationInputsIterator *i))->first);-            }|]-              >>= moveToForeignPtrWrapper-          outs <--            withDelete-              [C.block| Strings*{ -                Strings *r = new Strings();-                for (auto i : (*$(DerivationInputsIterator *i))->second) {-                  r->push_back(i);-                }-                return r;-              }|]-              toByteStrings-          [C.block| void { (*$(DerivationInputsIterator *i))++; }|]-          ((name, outs) :) <$> continue-#endif  instance Delete DerivationInputsIterator where   delete a = [C.block| void { delete $(DerivationInputsIterator *a); }|]@@ -1414,14 +992,10 @@      auto info2(*currentInfo);     info2.sigs.clear();-#if NIX_IS_AT_LEAST(2, 20, 0)     {       auto signer = std::make_unique<LocalSigner>(SecretKey { secretKey });       info2.sign(*store, *signer);     }-#else-    info2.sign(*store, secretKey);-#endif     assert(!info2.sigs.empty());     auto sig = *info2.sigs.begin(); @@ -1483,7 +1057,6 @@   IO (Maybe (Maybe (ForeignPtr (Ref ValidPathInfo)))) queryPathInfoFromClientCache (Store store) (StorePath pathFPtr) =   withForeignPtr pathFPtr \path ->-#if NIX_IS_AT_LEAST(2, 20, 0)   alloca \isKnownP -> do     mvpi <- [C.throwBlock| refValidPathInfo* {         ReceiveInterrupts _;@@ -1508,41 +1081,7 @@     isKnown <- peek isKnownP <&> (/= 0)     for (guard isKnown) \_ -> do       mvpi & traverseNonNull toForeignPtr-#else-  alloca \isKnownP -> do-    mvpi <- [C.throwBlock| refValidPathInfo* {-        ReceiveInterrupts _;-        Store &store = **$(refStore* store);-        StorePath &path = *$(nix::StorePath *path);-        bool &isKnown = *$(bool* isKnownP); -        std::string uri = store.getUri();-        ref<NarInfoDiskCache> cache = nix::getNarInfoDiskCache();--        // std::pair<nix::NarInfoDiskCache::Outcome, std::shared_ptr<NarInfo>>-        auto [outcome, maybeNarInfo] =-          cache->lookupNarInfo(uri, std::string(path.hashPart()));--        if (outcome == nix::NarInfoDiskCache::oValid) {-          assert(maybeNarInfo);-          isKnown = true;-          return new refValidPathInfo(maybeNarInfo);-        }-        else if (outcome == nix::NarInfoDiskCache::oInvalid) {-          isKnown = true;-          return nullptr;-        }-        else {-          // nix::NarInfoDiskCache::oUnknown or unexpected value-          isKnown = false;-          return nullptr;-        }-      }|]-    isKnown <- peek isKnownP <&> (/= 0)-    for (guard isKnown) \_ -> do-      mvpi & traverseNonNull toForeignPtr-#endif- instance Finalizer (Ref ValidPathInfo) where   finalizer = finalizeRefValidPathInfo -- must be CAF @@ -1570,13 +1109,7 @@ validPathInfoNarHash32 vpi =   unsafePackMallocCString     =<< [C.block| const char *{-#if NIX_IS_AT_LEAST(2,20,0)       std::string s((*$fptr-ptr:(refValidPathInfo* vpi))->narHash.to_string(nix::HashFormat::Nix32, true));-#elif NIX_IS_AT_LEAST(2,19,0)-      std::string s((*$fptr-ptr:(refValidPathInfo* vpi))->narHash.to_string(nix::HashFormat::Base32, true));-#else-      std::string s((*$fptr-ptr:(refValidPathInfo* vpi))->narHash.to_string(nix::Base32, true));-#endif       return stringdup(s);     }|] 
src/Hercules/CNix/Store/Instances.hs view
@@ -17,15 +17,9 @@  C.context $ context <> stdVectorCtx <> stdSetCtx -#if NIX_IS_AT_LEAST(2, 28, 0) C.include "<nix/store/path.hh>" C.include "<nix/store/derivations.hh>" C.include "<nix/store/path-with-outputs.hh>"-#else-C.include "<nix/path.hh>"-C.include "<nix/derivations.hh>"-C.include "<nix/path-with-outputs.hh>"-#endif  _ = Proxy :: Proxy NixStorePath 
src/Hercules/CNix/Util.hs view
@@ -25,17 +25,9 @@  C.context context -#if NIX_IS_AT_LEAST(2, 28, 0)- C.include "<nix/util/signals.hh>" -#else-C.include "<nix/config.h>"-C.include "<nix/util.hh>"-#  if NIX_IS_AT_LEAST(2,19,0)-C.include "<nix/signals.hh>"-#  endif-#endif+C.include "signals.hxx"  C.using "namespace nix" @@ -47,16 +39,21 @@  triggerInterrupt :: IO () triggerInterrupt =-#if NIX_IS_AT_LEAST(2,24,0)   [C.throwBlock| void {     nix::unix::triggerInterrupt();   } |]-#else-  [C.throwBlock| void {-    nix::triggerInterrupt();-  } |]-#endif +-- | Install a signal handler that will put Nix into the interrupted state and+-- throws 'UserInterrupt' in the main thread (as is usual), assuming this+-- function is called from the main thread.+--+-- This installs a synchronous C signal handler that calls nix::triggerInterrupt()+-- immediately when signals are delivered, eliminating race conditions between+-- signal delivery and interrupt flag setting. The handler then chains to any+-- previously installed handler to preserve existing behavior.+--+-- This may be removed from the library interface in the future, as it is no+-- longer needed to be called explicitly. installDefaultSigINTHandler :: IO () installDefaultSigINTHandler = do   mainThread <- myThreadId@@ -66,16 +63,11 @@         for_ mt \t -> do           throwTo t (toException UserInterrupt) -  -- Install Nix interrupter in Haskell-  _oldHandler <--    for [sigINT, sigTERM, sigHUP] \sig ->-      installHandler-        sig-        ( Catch do-            triggerInterrupt-            defaultHaskellHandler-        )-        Nothing+  -- Install synchronous C signal handlers first (these call triggerInterrupt immediately)+  for_ [sigINT, sigTERM, sigHUP] \sig -> do+    result <- [C.exp| int { hercules_install_signal_handler($(int sig)) } |]+    when (result /= 0) $+      panic $ "Failed to install synchronous signal handler for signal " <> show sig    -- Install dummy SIGUSR1 handler for Nix interrupt signal propagation   -- (installHandler uses process-wide sigprocmask, so this should apply to all
src/Hercules/CNix/Verbosity.hs view
@@ -20,16 +20,7 @@  C.context context -#if NIX_IS_AT_LEAST(2, 28, 0)- C.include "<nix/util/logging.hh>"--#else-C.include "<nix/config.h>"-C.include "<nix/error.hh>"-C.include "<nix/globals.hh>"-C.include "<nix/logging.hh>"-#endif  data Verbosity   = Error