about summary refs log tree commit diff
path: root/src/libstore/pathlocks.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2018-02-12T15·56+0100
committerEelco Dolstra <edolstra@gmail.com>2018-02-12T16·06+0100
commit4f09ce7940689887a18d4aa44367d2e6abeaa3cf (patch)
tree25f9fe61ac75c54cc60d8348b40593c9aa0112b5 /src/libstore/pathlocks.cc
parent35fd31770c589f28c569e7868f868a5b558cf83d (diff)
Fix 'deadlock: trying to re-acquire self-held lock'
This was caused by derivations with 'allowSubstitutes = false'. Such
derivations will be built locally. However, if there is another
SubstitionGoal that has the output of the first derivation in its
closure, then the path will be simultaneously built and substituted.

There was a check to catch this situation (via pathIsLockedByMe()),
but it no longer worked reliably because substitutions are now done in
another thread. (Thus the comment 'It can't happen between here and
the lockPaths() call below because we're not allowing multi-threading'
was no longer valid.)

The fix is to handle the path already being locked in both
SubstitutionGoal and DerivationGoal.
Diffstat (limited to 'src/libstore/pathlocks.cc')
-rw-r--r--src/libstore/pathlocks.cc6
1 files changed, 4 insertions, 2 deletions
diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc
index 587f29598851..08d1efdbeb01 100644
--- a/src/libstore/pathlocks.cc
+++ b/src/libstore/pathlocks.cc
@@ -113,8 +113,10 @@ bool PathLocks::lockPaths(const PathSet & _paths,
 
         {
             auto lockedPaths(lockedPaths_.lock());
-            if (lockedPaths->count(lockPath))
-                throw Error("deadlock: trying to re-acquire self-held lock '%s'", lockPath);
+            if (lockedPaths->count(lockPath)) {
+                if (!wait) return false;
+                throw AlreadyLocked("deadlock: trying to re-acquire self-held lock '%s'", lockPath);
+            }
             lockedPaths->insert(lockPath);
         }