1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-13 14:02:42 +01:00

Communicate with the gc daemon via a socket

This commit is contained in:
Théophane Hufschmitt 2022-04-11 10:20:36 +02:00
parent aadf585ea3
commit 26c802d18c

View file

@ -25,6 +25,7 @@ namespace nix {
static std::string gcSocketPath = "/gc-socket/socket"; static std::string gcSocketPath = "/gc-socket/socket";
static std::string rootsSocketPath = "/gc-roots-socket/socket";
static std::string gcRootsDir = "gcroots"; static std::string gcRootsDir = "gcroots";
@ -122,7 +123,7 @@ void LocalStore::addTempRoot(const StorePath & path)
collector is running. So we have to connect to the garbage collector is running. So we have to connect to the garbage
collector and inform it about our root. */ collector and inform it about our root. */
if (!state->fdRootsSocket) { if (!state->fdRootsSocket) {
auto socketPath = stateDir.get() + gcSocketPath; auto socketPath = stateDir.get() + rootsSocketPath;
debug("connecting to '%s'", socketPath); debug("connecting to '%s'", socketPath);
state->fdRootsSocket = createUnixDomainSocket(); state->fdRootsSocket = createUnixDomainSocket();
try { try {
@ -296,25 +297,31 @@ Roots LocalStore::findRoots(bool censor)
{ {
Roots roots; Roots roots;
Pipe fromHelper; auto fd = AutoCloseFD(socket(PF_UNIX, SOCK_STREAM
fromHelper.create(); #ifdef SOCK_CLOEXEC
Pid helperPid = startProcess([&]() { | SOCK_CLOEXEC
if (dup2(fromHelper.writeSide.get(), STDOUT_FILENO) == -1) #endif
throw SysError("cannot pipe standard output into log file"); , 0));
if (chdir("/") == -1) throw SysError("changing into /"); if (!fd)
auto helperProgram = settings.nixLibexecDir + "/nix/nix-find-roots"; throw SysError("cannot create Unix domain socket");
Strings args = {std::string(baseNameOf(helperProgram))}; closeOnExec(fd.get());
execv(
helperProgram.c_str(),
stringsToCharPtrs(args).data()
);
throw SysError("executing '%s'", helperProgram); // FIXME: Dont hardcode
}); string socketPath = "/nix/var/nix/gc-socket/socket";
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
if (socketPath.size() + 1 >= sizeof(addr.sun_path))
throw Error("socket path '%1%' is too long", socketPath);
strcpy(addr.sun_path, socketPath.c_str());
if (::connect(fd.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
throw SysError("cannot connect to the gc daemon at '%1%'", socketPath);
try { try {
while (true) { while (true) {
auto line = readLine(fromHelper.readSide.get()); auto line = readLine(fd.get());
if (line.empty()) break; // TODO: Handle the broken symlinks if (line.empty()) break; // TODO: Handle the broken symlinks
auto parsedLine = tokenizeString<std::vector<std::string>>(line, "\t"); auto parsedLine = tokenizeString<std::vector<std::string>>(line, "\t");
if (parsedLine.size() != 2) if (parsedLine.size() != 2)
@ -328,10 +335,6 @@ Roots LocalStore::findRoots(bool censor)
} catch (EndOfFile &) { } catch (EndOfFile &) {
} }
int res = helperPid.wait();
if (res != 0)
throw Error("unable to start the gc helper process");
return roots; return roots;
} }
@ -524,7 +527,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
FdLock gcLock(fdGCLock.get(), ltWrite, true, "waiting for the big garbage collector lock..."); FdLock gcLock(fdGCLock.get(), ltWrite, true, "waiting for the big garbage collector lock...");
/* Start the server for receiving new roots. */ /* Start the server for receiving new roots. */
auto socketPath = stateDir.get() + gcSocketPath; auto socketPath = stateDir.get() + rootsSocketPath;
createDirs(dirOf(socketPath)); createDirs(dirOf(socketPath));
auto fdServer = createUnixDomainSocket(socketPath, 0666); auto fdServer = createUnixDomainSocket(socketPath, 0666);