* Don't delete active lock files.
This commit is contained in:
		
							parent
							
								
									1328aa3307
								
							
						
					
					
						commit
						33c5d23b81
					
				
					 5 changed files with 39 additions and 9 deletions
				
			
		|  | @ -194,9 +194,35 @@ void collectGarbage(const PathSet & roots, GCAction action, | ||||||
|         debug(format("dead path `%1%'") % path); |         debug(format("dead path `%1%'") % path); | ||||||
|         result.insert(path); |         result.insert(path); | ||||||
| 
 | 
 | ||||||
|  |         AutoCloseFD fdLock; | ||||||
|  | 
 | ||||||
|         if (action == gcDeleteDead) { |         if (action == gcDeleteDead) { | ||||||
|             printMsg(lvlInfo, format("deleting `%1%'") % path); |             printMsg(lvlInfo, format("deleting `%1%'") % path); | ||||||
|  | 
 | ||||||
|  |             /* Only delete a lock file if we can acquire a write lock
 | ||||||
|  |                on it.  That means that it's either stale, or the | ||||||
|  |                process that created it hasn't locked it yet.  In the | ||||||
|  |                latter case the other process will detect that we | ||||||
|  |                deleted the lock, and retry (see pathlocks.cc). */ | ||||||
|  |             if (path.size() >= 5 && string(path, path.size() - 5) == ".lock") { | ||||||
|  | 
 | ||||||
|  |                 fdLock = open(path.c_str(), O_RDWR); | ||||||
|  |                 if (fdLock == -1) { | ||||||
|  |                     if (errno == ENOENT) continue; | ||||||
|  |                     throw SysError(format("opening lock file `%1%'") % path); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if (!lockFile(fdLock, ltWrite, false)) { | ||||||
|  |                     debug(format("skipping active lock `%1%'") % path); | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |              | ||||||
|             deleteFromStore(path); |             deleteFromStore(path); | ||||||
|  | 
 | ||||||
|  |             if (fdLock != -1) | ||||||
|  |                 /* Write token to stale (deleted) lock file. */ | ||||||
|  |                 writeFull(fdLock, (const unsigned char *) "d", 1); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /* Only delete lock files if the path is belongs to doesn't
 |         /* Only delete lock files if the path is belongs to doesn't
 | ||||||
|  |  | ||||||
|  | @ -16,7 +16,9 @@ void collectGarbage(const PathSet & roots, GCAction action, | ||||||
|     PathSet & result); |     PathSet & result); | ||||||
| 
 | 
 | ||||||
| /* Register a temporary GC root.  This root will automatically
 | /* Register a temporary GC root.  This root will automatically
 | ||||||
|    disappear when this process exits. */ |    disappear when this process exits.  WARNING: this function should | ||||||
|  |    not be called inside a BDB transaction, otherwise we can | ||||||
|  |    deadlock. */ | ||||||
| void addTempRoot(const Path & path); | void addTempRoot(const Path & path); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -127,9 +127,8 @@ PathLocks::~PathLocks() | ||||||
|             /* Write a (meaningless) token to the file to indicate to
 |             /* Write a (meaningless) token to the file to indicate to
 | ||||||
|                other processes waiting on this lock that the lock is |                other processes waiting on this lock that the lock is | ||||||
|                stale (deleted). */ |                stale (deleted). */ | ||||||
|             if (write(i->first, "d", 1) == 1) { |             unlink(i->second.c_str()); | ||||||
|                 unlink(i->second.c_str()); |             writeFull(i->first, (const unsigned char *) "d", 1); | ||||||
|             } |  | ||||||
|             /* Note that the result of unlink() is ignored; removing
 |             /* Note that the result of unlink() is ignored; removing
 | ||||||
|                the lock file is an optimisation, not a necessity. */ |                the lock file is an optimisation, not a necessity. */ | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -36,10 +36,10 @@ nix-pull.sh: dependencies.nix | ||||||
| gc.sh: dependencies.nix | gc.sh: dependencies.nix | ||||||
| gc-concurrent.sh: gc-concurrent.nix | gc-concurrent.sh: gc-concurrent.nix | ||||||
| 
 | 
 | ||||||
| #TESTS = init.sh hash.sh lang.sh simple.sh dependencies.sh locking.sh parallel.sh \ | TESTS = init.sh hash.sh lang.sh simple.sh dependencies.sh locking.sh parallel.sh \ | ||||||
| #  build-hook.sh substitutes.sh substitutes2.sh fallback.sh nix-push.sh gc.sh \ |   build-hook.sh substitutes.sh substitutes2.sh fallback.sh nix-push.sh gc.sh \ | ||||||
| #  gc-concurrent.sh verify.sh nix-pull.sh |   gc-concurrent.sh verify.sh nix-pull.sh | ||||||
| TESTS = init.sh gc-concurrent.sh  | #TESTS = init.sh gc-concurrent.sh  | ||||||
| 
 | 
 | ||||||
| XFAIL_TESTS = | XFAIL_TESTS = | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,4 +6,7 @@ echo $(cat $input1/foo)$(cat $input2/bar) > $out/foobar | ||||||
| sleep 5 | sleep 5 | ||||||
| mkdir $out || true | mkdir $out || true | ||||||
| 
 | 
 | ||||||
| ln -s $input2 $out/input-2 | # Check that the GC hasn't deleted the lock on our output. | ||||||
|  | test -e "$out.lock" | ||||||
|  | 
 | ||||||
|  | ln -s $input2 $out/input-2 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue