mirror of
https://github.com/NixOS/nix
synced 2025-07-06 21:41:48 +02:00
* nix-store, nix-instantiate: added an option `--add-root' to
immediately add the result as a permanent GC root. This is the only way to prevent a race with the garbage collector. For instance, the old style ln -s $(nix-store -r $(nix-instantiate foo.nix)) \ /nix/var/nix/gcroots/result has two time windows in which the garbage collector can interfere (by GC'ing the derivation and the output, respectively). On the other hand, nix-store --add-root /nix/var/nix/gcroots/result -r \ $(nix-instantiate --add-root /nix/var/nix/gcroots/drv \ foo.nix) is safe. * nix-build: use `--add-root' to prevent GC races.
This commit is contained in:
parent
a6b65fd5e1
commit
dcc37c236c
11 changed files with 165 additions and 17 deletions
|
@ -42,3 +42,5 @@ Options:
|
|||
|
||||
--verbose / -v: verbose operation (may be repeated)
|
||||
--keep-failed / -K: keep temporary directories of failed builds
|
||||
|
||||
--add-root: add garbage collector roots for the result
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "globals.hh"
|
||||
#include "build.hh"
|
||||
#include "gc.hh"
|
||||
|
@ -18,6 +22,10 @@ void printHelp()
|
|||
}
|
||||
|
||||
|
||||
static Path gcRoot;
|
||||
static int rootNr = 0;
|
||||
|
||||
|
||||
static Path findOutput(const Derivation & drv, string id)
|
||||
{
|
||||
for (DerivationOutputs::const_iterator i = drv.outputs.begin();
|
||||
|
@ -27,6 +35,22 @@ static Path findOutput(const Derivation & drv, string id)
|
|||
}
|
||||
|
||||
|
||||
static Path followSymlinks(Path & path)
|
||||
{
|
||||
while (!isStorePath(path)) {
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting status of `%1%'") % path);
|
||||
if (!S_ISLNK(st.st_mode)) return path;
|
||||
string target = readLink(path);
|
||||
path = canonPath(string(target, 0, 1) == "/"
|
||||
? target
|
||||
: path + "/" + target);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/* Realisation the given path. For a derivation that means build it;
|
||||
for other paths it means ensure their validity. */
|
||||
static Path realisePath(const Path & path)
|
||||
|
@ -35,7 +59,14 @@ static Path realisePath(const Path & path)
|
|||
PathSet paths;
|
||||
paths.insert(path);
|
||||
buildDerivations(paths);
|
||||
return findOutput(derivationFromPath(path), "out");
|
||||
Path outPath = findOutput(derivationFromPath(path), "out");
|
||||
|
||||
if (gcRoot == "")
|
||||
printGCWarning();
|
||||
else
|
||||
outPath = addPermRoot(outPath, makeRootName(gcRoot, rootNr));
|
||||
|
||||
return outPath;
|
||||
} else {
|
||||
ensurePath(path);
|
||||
return path;
|
||||
|
@ -48,6 +79,10 @@ static void opRealise(Strings opFlags, Strings opArgs)
|
|||
{
|
||||
if (!opFlags.empty()) throw UsageError("unknown flag");
|
||||
|
||||
for (Strings::iterator i = opArgs.begin();
|
||||
i != opArgs.end(); i++)
|
||||
*i = followSymlinks(*i);
|
||||
|
||||
if (opArgs.size() > 1) {
|
||||
PathSet drvPaths;
|
||||
for (Strings::iterator i = opArgs.begin();
|
||||
|
@ -374,8 +409,8 @@ void run(Strings args)
|
|||
Strings opFlags, opArgs;
|
||||
Operation op = 0;
|
||||
|
||||
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
|
||||
string arg = *i;
|
||||
for (Strings::iterator i = args.begin(); i != args.end(); ) {
|
||||
string arg = *i++;
|
||||
|
||||
Operation oldOp = op;
|
||||
|
||||
|
@ -403,6 +438,11 @@ void run(Strings args)
|
|||
op = opInit;
|
||||
else if (arg == "--verify")
|
||||
op = opVerify;
|
||||
else if (arg == "--add-root") {
|
||||
if (i == args.end())
|
||||
throw UsageError("`--add-root requires an argument");
|
||||
gcRoot = *i++;
|
||||
}
|
||||
else if (arg[0] == '-')
|
||||
opFlags.push_back(arg);
|
||||
else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue