* 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