about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstore/gc.cc44
1 files changed, 29 insertions, 15 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index c89f7a8a1ee4..cff503784520 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -12,17 +12,30 @@
 #include <unistd.h>
 
 
-/* Acquire the global GC lock. */
-static AutoCloseFD openGCLock(LockType lockType)
+static string gcLockName = "gc.lock";
+
+
+/* Acquire the global GC lock.  This is used to prevent new Nix
+   processes from starting after the temporary root files have been
+   read.  To be precise: when they try to create a new temporary root
+   file, they will block until the garbage collector has finished /
+   yielded the GC lock. */
+static int openGCLock(LockType lockType)
 {
-#if 0
-    Path fnGCLock = (format("%1%/%2%/%3%")
-        % nixStateDir % tempRootsDir % getpid()).str();
+    Path fnGCLock = (format("%1%/%2%")
+        % nixStateDir % gcLockName).str();
         
-    fdTempRoots = open(fnTempRoots.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0600);
-    if (fdTempRoots == -1)
-        throw SysError(format("opening temporary roots file `%1%'") % fnTempRoots);
-#endif
+    AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT, 0600);
+    if (fdGCLock == -1)
+        throw SysError(format("opening global GC lock `%1%'") % fnGCLock);
+
+    lockFile(fdGCLock, lockType, true);
+
+    /* !!! Restrict read permission on the GC root.  Otherwise any
+       process that can open the file for reading can DoS the
+       collector. */
+    
+    return fdGCLock.borrow();
 }
 
 
@@ -41,11 +54,15 @@ void addTempRoot(const Path & path)
         while (1) {
             fnTempRoots = (format("%1%/%2%/%3%")
                 % nixStateDir % tempRootsDir % getpid()).str();
-        
+
+            AutoCloseFD fdGCLock = openGCLock(ltRead);
+            
             fdTempRoots = open(fnTempRoots.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0600);
             if (fdTempRoots == -1)
                 throw SysError(format("opening temporary roots file `%1%'") % fnTempRoots);
 
+            fdGCLock.close();
+            
             debug(format("acquiring read lock on `%1%'") % fnTempRoots);
             lockFile(fdTempRoots, ltRead, true);
 
@@ -188,14 +205,11 @@ void collectGarbage(const PathSet & roots, GCAction action,
 {
     result.clear();
     
-    /* !!! TODO: Acquire the global GC root.  This prevents
+    /* Acquire the global GC root.  This prevents
        a) New roots from being added.
        b) Processes from creating new temporary root files. */
+    AutoCloseFD fdGCLock = openGCLock(ltWrite);
 
-    /* !!! Restrict read permission on the GC root.  Otherwise any
-       process that can open the file for reading can DoS the
-       collector. */
-    
     /* Determine the live paths which is just the closure of the
        roots under the `references' relation. */
     PathSet livePaths;