summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-04-30 10:58:04 -0400
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-04-30 10:58:04 -0400
commit46cdc6ad51376e2f31ce806ee38e697d00a6e5cb (patch)
treef8bafa8d4c93eb8af99a5b92fe37b6b430ffaa86
parentc722193a91cb32f2696d655cf6301cf5ccfae6ce (diff)
downloadguix-46cdc6ad51376e2f31ce806ee38e697d00a6e5cb.tar.gz
Handle EPERM when creating a hard link for the chroot
There is a race condition when doing parallel builds with chroots and
the immutable bit enabled.  One process may call makeImmutable()
before the other has called link(), in which case link() will fail
with EPERM.  We could retry or wrap the operation in a lock, but since
this condition is rare and I'm lazy, we just use the existing copy
fallback.

Fixes #9.
-rw-r--r--src/libstore/build.cc7
1 files changed, 5 insertions, 2 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 77e968ddd0..acc2923059 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1708,8 +1708,11 @@ void DerivationGoal::startBuilder()
                     /* Hard-linking fails if we exceed the maximum
                        link count on a file (e.g. 32000 of ext3),
                        which is quite possible after a `nix-store
-                       --optimise'.  Make a copy instead. */
-                    if (errno != EMLINK)
+                       --optimise'.  It can also fail if another
+                       process called makeImmutable() on *i after we
+                       did makeMutable().  In those cases, make a copy
+                       instead. */
+                    if (errno != EMLINK && errno != EPERM)
                         throw SysError(format("linking `%1%' to `%2%'") % p % *i);
                     StringSink sink;
                     dumpPath(*i, sink);