about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-07-19T16·49+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-07-19T16·49+0000
commitebcccbd3581d34d7fefb975c0255a39a3e39e122 (patch)
tree525a524bf1fe7ceeab37e92cdfa36f999dd174fb
parent88e54153dce2cdba9a075d9dbc81ad81e7e73435 (diff)
* Added a tool to find additional roots for the garbage collector,
  such as open files, current directories, mmaped files, etc.  This is
  inherently unportable, but it's easy to adapt this script to other
  platforms.  Currently we call `lsof' and try to read various bits in
  /proc/NNN.

  The goal is to prevent the garbage collector from removing store
  paths that are no longer reachable from a permanent root but that
  are still in use (for instance, after the user has done "nix-env -e"
  on a running program).

-rw-r--r--scripts/Makefile.am6
-rw-r--r--scripts/find-runtime-roots.pl.in58
2 files changed, 62 insertions, 2 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index bffbdbde5ddd..7b0aef061b3a 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -7,13 +7,14 @@ noinst_SCRIPTS = nix-profile.sh generate-patches.pl
 
 nix-pull nix-push: readmanifest.pm readconfig.pm download-using-manifests.pl
 
-install-exec-local: readmanifest.pm download-using-manifests.pl
+install-exec-local: readmanifest.pm download-using-manifests.pl find-runtime-roots.pl
 	$(INSTALL) -d $(DESTDIR)$(sysconfdir)/profile.d
 	$(INSTALL_PROGRAM) nix-profile.sh $(DESTDIR)$(sysconfdir)/profile.d/nix.sh
 	$(INSTALL) -d $(DESTDIR)$(libexecdir)/nix
 	$(INSTALL_DATA) readmanifest.pm $(DESTDIR)$(libexecdir)/nix 
 	$(INSTALL_DATA) readconfig.pm $(DESTDIR)$(libexecdir)/nix 
 	$(INSTALL_PROGRAM) download-using-manifests.pl $(DESTDIR)$(libexecdir)/nix 
+	$(INSTALL_PROGRAM) find-runtime-roots.pl $(DESTDIR)$(libexecdir)/nix 
 	$(INSTALL) -d $(DESTDIR)$(sysconfdir)/nix
 
 include ../substitute.mk
@@ -27,4 +28,5 @@ EXTRA_DIST = nix-collect-garbage.in \
   nix-build.in \
   download-using-manifests.pl.in \
   generate-patches.pl.in \
-  nix-pack-closure.in nix-unpack-closure.in
+  nix-pack-closure.in nix-unpack-closure.in \
+  find-runtime-roots.pl.in
diff --git a/scripts/find-runtime-roots.pl.in b/scripts/find-runtime-roots.pl.in
new file mode 100644
index 000000000000..3e55ee4458d3
--- /dev/null
+++ b/scripts/find-runtime-roots.pl.in
@@ -0,0 +1,58 @@
+#! @perl@ -w
+
+use strict;
+
+my $procDir = "/proc";
+
+
+sub readProc {
+    return unless -d $procDir;
+
+    opendir DIR, $procDir or return;
+    
+    foreach my $name (readdir DIR) {
+        next unless $name =~ /^\d+$/;
+
+        my $process = "$procDir/$name";
+
+        #print STDERR "=== $process\n";
+        
+        my $target;
+        print "$target\n" if $target = readlink "$process/exe";
+        print "$target\n" if $target = readlink "$process/cwd";
+
+        if (opendir FDS, "$process/fd") {
+            foreach my $name (readdir FDS) {
+                $target = readlink "$process/fd/$name";
+                print "$target\n" if $target && substr($target, 0, 1) eq "/";
+            }
+            closedir FDS;
+        }
+
+        if (open MAP, "<$process/maps") {
+            while (<MAP>) {
+                next unless /^ \s* \S+ \s+ \S+ \s+ \S+ \s+ \S+ \s+ \S+ \s+ (\/\S+) \s* $/x;
+                print "$1\n";
+            }
+            close MAP;
+        }
+    }
+
+    closedir DIR;
+}
+
+
+sub lsof {
+    return unless open LSOF, "lsof -b -w -F n |";
+
+    while (<LSOF>) {
+        next unless /^n (\/ .*)$/x;
+        print $1, "\n";
+    }
+
+    close LSOF;
+}
+
+
+readProc;
+lsof;