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 +7/−0
- cbits/signals.cxx +65/−0
- cbits/signals.hxx +17/−0
- hercules-ci-cnix-store.cabal +9/−24
- include/hercules-ci-cnix/store.hxx +0/−8
- src/Hercules/CNix.hs +7/−19
- src/Hercules/CNix/Exception.hs +30/−10
- src/Hercules/CNix/Settings.hs +0/−5
- src/Hercules/CNix/Store.hs +0/−467
- src/Hercules/CNix/Store/Instances.hs +0/−6
- src/Hercules/CNix/Util.hs +17/−25
- src/Hercules/CNix/Verbosity.hs +0/−9
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