about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-11-29T09·15+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-11-29T09·15+0000
commitbd48fd97f646f068ae2725b5b2f048d45866119b (patch)
treef816350e1a1c66b0cb783a49d5b9a3da57e31ff6
parent703e5a2ce2f111c5329a8448ba47a7fbe11ad6cd (diff)
* Impose a configurable time limit on patch generation. This is
  necessary because bsdiff has some pathological worst-case behaviour,
  e.g. O(n^2) on files consisting only of 0s.

-rwxr-xr-xscripts/generate-patches.pl.in18
1 files changed, 12 insertions, 6 deletions
diff --git a/scripts/generate-patches.pl.in b/scripts/generate-patches.pl.in
index dba6473508d3..3be30be00b86 100755
--- a/scripts/generate-patches.pl.in
+++ b/scripts/generate-patches.pl.in
@@ -15,6 +15,9 @@ $maxNarSize = 100 * 1024 * 1024 if !defined $maxNarSize;
 my $maxPatchFraction = $ENV{"NIX_PATCH_FRACTION"};
 $maxPatchFraction = 0.60 if !defined $maxPatchFraction;
 
+my $timeLimit = $ENV{"NIX_BSDIFF_TIME_LIMIT"};
+$timeLimit = 180 if !defined $timeLimit;
+
 
 die unless scalar @ARGV == 5;
 
@@ -29,8 +32,6 @@ my $dstManifest = $ARGV[4];
 my $tmpDir = tempdir("nix-generate-patches.XXXXXX", CLEANUP => 1, TMPDIR => 1)
     or die "cannot create a temporary directory";
 
-print "TEMP = $tmpDir\n";
-
 #END { rmdir $tmpDir; }
 
 my %srcNarFiles;
@@ -223,7 +224,7 @@ foreach my $p (keys %dstOutPaths) {
 
     foreach my $q (keys %srcOutPaths) {
         (my $name2, my $version2) = getNameVersion $q;
-	next unless defined $name2 && defined $version2;
+        next unless defined $name2 && defined $version2;
 
         if ($name eq $name2) {
 
@@ -312,8 +313,13 @@ foreach my $p (keys %dstOutPaths) {
             next;
         }
         
-        system("@libexecdir@/bsdiff $tmpDir/A $tmpDir/B $tmpDir/DIFF") == 0
-            or die "cannot compute binary diff";
+        my $time1 = time();
+        my $res = system("ulimit -t $timeLimit; @libexecdir@/bsdiff $tmpDir/A $tmpDir/B $tmpDir/DIFF");
+        my $time2 = time();
+        if ($res) {
+            warn "binary diff computation aborted after ", $time2 - $time1, " seconds\n";
+            next;
+        }
 
         my $baseHash = `@bindir@/nix-hash --flat --type $hashAlgo --base32 $tmpDir/A` or die;
         chomp $baseHash;
@@ -327,7 +333,7 @@ foreach my $p (keys %dstOutPaths) {
         my $narDiffSize = (stat "$tmpDir/DIFF")[7];
         my $dstNarBz2Size = (stat $dstNarBz2)[7];
 
-        print "    size $narDiffSize; full size $dstNarBz2Size\n";
+        print "    size $narDiffSize; full size $dstNarBz2Size; ", $time2 - $time1, " seconds\n";
         
         if ($narDiffSize >= $dstNarBz2Size) {
             print "    rejecting; patch bigger than full archive\n";