diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 9e93cdaa9..cf3697b12 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -3,6 +3,7 @@ #include "local-store.hh" #include "local-fs-store.hh" #include "finally.hh" +#include "find-roots.hh" #include #include @@ -284,14 +285,28 @@ void LocalStore::findRootsNoTempNoExternalDaemon(Roots & roots, bool censor) { debug("Can’t connect to the tracing daemon socket, fallback to the internal trace"); - /* Process direct roots in {gcroots,profiles}. */ - findRoots(stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots); - findRoots(stateDir + "/profiles", DT_UNKNOWN, roots); + using namespace nix::roots_tracer; - /* Add additional roots returned by different platforms-specific - heuristics. This is typically used to add running programs to - the set of roots (to prevent them from being garbage collected). */ - findRuntimeRoots(roots, censor); + const TracerConfig opts { + .storeDir = fs::path(storeDir), + .stateDir = fs::path(stateDir.get()) + }; + const std::set standardRoots = { + opts.stateDir / fs::path(gcRootsDir), + opts.stateDir / fs::path("gcroots"), + }; + auto traceResult = traceStaticRoots(opts, standardRoots); + auto runtimeRoots = getRuntimeRoots(opts); + traceResult.storeRoots.insert(runtimeRoots.begin(), runtimeRoots.end()); + for (auto & [rawRootInStore, externalRoots] : traceResult.storeRoots) { + if (!isInStore(rawRootInStore)) continue; + auto rootInStore = toStorePath(rawRootInStore).first; + if (!isValidPath(rootInStore)) continue; + std::unordered_set primRoots; + for (const auto & externalRoot : externalRoots) + primRoots.insert(externalRoot.string()); + roots.emplace(rootInStore, primRoots); + } } diff --git a/src/libstore/local.mk b/src/libstore/local.mk index b992bcbc0..31daf4eac 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -6,7 +6,7 @@ libstore_DIR := $(d) libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc $(d)/build/*.cc) -libstore_LIBS = libutil +libstore_LIBS = libutil find-roots libstore_LDFLAGS += $(SQLITE3_LIBS) $(LIBCURL_LIBS) $(SODIUM_LIBS) -pthread ifdef HOST_LINUX @@ -32,7 +32,7 @@ ifeq ($(HAVE_SECCOMP), 1) endif libstore_CXXFLAGS += \ - -I src/libutil -I src/libstore -I src/libstore/build \ + -I src/libutil -I src/libstore -I src/libstore/build -I src/nix-find-roots/lib \ -DNIX_PREFIX=\"$(prefix)\" \ -DNIX_STORE_DIR=\"$(storedir)\" \ -DNIX_DATA_DIR=\"$(datadir)\" \ diff --git a/src/nix-find-roots/lib/find-roots.hh b/src/nix-find-roots/lib/find-roots.hh index b58f9c1fd..504fdd768 100644 --- a/src/nix-find-roots/lib/find-roots.hh +++ b/src/nix-find-roots/lib/find-roots.hh @@ -26,9 +26,9 @@ inline void logNone(std::string_view) { } struct TracerConfig { - fs::path storeDir = "/nix/store"; - fs::path stateDir = "/nix/var/nix"; - fs::path socketPath = "/nix/var/nix/gc-socket/socket"; + const fs::path storeDir = "/nix/store"; + const fs::path stateDir = "/nix/var/nix"; + const fs::path socketPath = "/nix/var/nix/gc-socket/socket"; std::function log = logNone; std::function debug = logNone; diff --git a/src/nix-find-roots/main.cc b/src/nix-find-roots/main.cc index ff8856d26..d93e7eee7 100644 --- a/src/nix-find-roots/main.cc +++ b/src/nix-find-roots/main.cc @@ -15,8 +15,12 @@ void logStderr(std::string_view msg) TracerConfig parseCmdLine(int argc, char** argv) { - TracerConfig res; - res.log = logStderr; + std::function log = logStderr; + std::function debug = logNone; + fs::path storeDir = "/nix/store"; + fs::path stateDir = "/nix/var/nix"; + fs::path socketPath = "/nix/var/nix/gc-trace-socket/socket"; + auto usage = [&]() { std::cerr << "Usage: " << string(argv[0]) << " [--verbose|-v] [-s storeDir] [-d stateDir] [-l socketPath]" << std::endl; exit(1); @@ -40,23 +44,28 @@ TracerConfig parseCmdLine(int argc, char** argv) usage(); break; case 'v': - res.debug = logStderr; + debug = logStderr; break; case 's': - res.storeDir = fs::path(optarg); + storeDir = fs::path(optarg); break; case 'd': - res.stateDir = fs::path(optarg); + stateDir = fs::path(optarg); break; case 'l': - res.socketPath = fs::path(optarg); + socketPath = fs::path(optarg); break; default: std::cerr << "Got invalid char: " << (char)opt_char << std::endl; abort(); } }; - return res; + return TracerConfig { + .storeDir = storeDir, + .stateDir = stateDir, + .socketPath = socketPath, + .debug = debug, + }; }