On Tue, Jun 15, 2010 at 11:05:58PM +0800, Michael Deegan wrote:
> retitle 585804 apt-cacher-cleanup: infinite loop in the face of corrupted gz
> files
> thanks
>
> On Mon, Jun 14, 2010 at 08:45:31AM +0100, Mark Hindley wrote:
> > It might be worth creating a lock so only a single instance can run, but
> > I am not sure that will address your root issue.
>
> Agreed.
Patch for this:
diff --git a/apt-cacher-cleanup.pl b/apt-cacher-cleanup.pl
index 149fcce..5e1c8c7 100755
--- a/apt-cacher-cleanup.pl
+++ b/apt-cacher-cleanup.pl
@@ -83,6 +84,7 @@ if ( $cfg->{clean_cache} ne 1 ) {
printmsg("Maintenance disallowed by configuration item clean_cache\n");
exit 0;
}
+
# change uid and gid if root
if ($cfg->{user} && !$> or $cfg->{group} && !$)) {
printmsg("Invoked as root, changing to $cfg->{user}:$cfg->{group} and
re-execing.\n");
@@ -543,6 +545,14 @@ if (@db_mode || $db_recover){
# Cache cleaning from here
+# Take a lock on the cache dir to ensure only one cleanup script can run at a
+# time as this can take a while on some systems.
+
+open (my $cleanup_lock, '<', $cfg->{'cache_dir'})
+ or die "Can't open $cfg->{'cache_dir'} for locking!\nError: $!\n";
+flock $cleanup_lock, LOCK_EX|LOCK_NB
+ or die "Another apt-cacher-cleanup is already running. Exiting!\n";
+
# check offline mode in config
if (defined $cfg->{offline_mode} && $cfg->{offline_mode}) {
$offline = 1;
> > > While the machine is not exactly fast, under normal circumstances cleanup
> > > should take "only" 3 or 4 hours. :P
> >
> > What spec is this? I have a k6 200 that takes only about 20 minutes!
>
> Dual-PIII 1GHz, 256MB, ST318406LW.
>
> For me cleanup has always taken hours, and involved considerable amounts of
> disk I/O.
>
> > How large is the cache? How much free space?
>
> mich...@ying:~$ du -skx /var/cache/apt-cacher/*
> 16196 /var/cache/apt-cacher/headers
> 4 /var/cache/apt-cacher/import
> 0 /var/cache/apt-cacher/libcurl.socket
> 3467600 /var/cache/apt-cacher/packages
> 15364 /var/cache/apt-cacher/private
> 28 /var/cache/apt-cacher/temp
>
> mich...@ying:~$ df -P / /var/cache/apt-cacher/
> Filesystem 1024-blocks Used Available Capacity Mounted on
> /dev/sda2 3937252 962408 2774836 26% /
> /dev/mapper/ying-home 4128448 3917760 976 100% /home
>
> (shortly before I freed up some space (by deleting a half-gigabyte .deb))
>
> Admittedly the lack of diskspace was hardly an ideal situation, but I was
> kind of hoping for it to keel over with an error rather than just spinning
> quietly. :P
>
> The cache services five machines, a mixture of Ubuntu/Debian and 32/64 bit
> (yes, I know, cruel and unusual). Different files with the same name are
> usually not a problem.
>
> > We need to find out if it is just taking more than 24 hours and then the
> > second instance compounds the issue.
>
> It appears the answer is 'no'.
>
> > Can you change /etc/cron.daily/apt-cacher and add '-v' to the script
> > invocation. You will get an email with basic information about what it
> > is doing.
>
> I'm not sure why I didn't think to try that...
>
> > Is there anything in the logs
> > (/var/log/apt-cacher/{db|access|error}.log?
>
> error.log naturally has lots of noise complaining about diskspace, eg:
>
> Mon Jun 14 15:30:26 2010|info [19753]: return_file
> /var/cache/apt-cacher/packages/security.debian.org_dists_lenny_updates_main_binary-i386_Packages.diff_Index
> aborted by timeout at 0 of bytes
> Mon Jun 14 15:31:34 2010|info [21203]: ALARM: Insuffient diskspace for
> Content-Length: 51900 in cache_dir with 36864 freespace
> Mon Jun 14 15:31:45 2010|warn [21205]: Close
> /var/cache/apt-cacher/packages/security.debian.org_dists_squeeze_updates_contrib_binary-i386_Packages.diff_Index
> failed, No space left on device at /usr/sbin/apt-cacher line 1481.
>
> access.log contains a few dozen CLEANUPREFRESH entries, plus the normal stuff
> from clients.
>
> db.log does not exist.
>
> I think I have found the problem, though. After killing a couple of runs
> with -v, I noticed that it had stopped at the same file. The following test
> script and attached test file will hopefully demonstrate the problem:
Can you try this patch please? Does it help?
diff --git a/apt-cacher-cleanup.pl b/apt-cacher-cleanup.pl
index 149fcce..a90a61c 100755
--- a/apt-cacher-cleanup.pl
+++ b/apt-cacher-cleanup.pl
@@ -236,16 +237,15 @@ sub pdiff {
printmsg "Reading $basename...\n";
while (<$raw>){
+ last if $AnyUncompressError;
print $tfh $_;
$sha1->add($_);
}
close($raw);
flock($lck, LOCK_UN);
close($lck,);
- my $rstat =($? >> 8);
- # printmsg "Read status $rstat\n";
- if ($rstat) {
- warn "$name Read failed, aborting patch\n";
+ if ($AnyUncompressError) {
+ warn "$name Read failed: $AnyUncompressError. Aborting patch\n";
return;
}
@@ -332,10 +332,15 @@ sub pdiff {
my $pdfh = new IO::Uncompress::AnyUncompress $pdiff
or die "Decompression failed: $AnyUncompressError\n";
while (<$pdfh>) {
+ last if $AnyUncompressError;
print DIFFS $_;
$sha1->add($_);
}
close($pdfh);
+ if ($AnyUncompressError) {
+ warn "$name Read failed: $AnyUncompressError. Aborting patch\n";
+ return;
+ }
my $pdiffdigest = $sha1->hexdigest;
# printmsg "$pdiff SHA1: $pdiffdigest\n";
@@ -356,7 +361,7 @@ sub pdiff {
print $patchpipe $diffs;
close($patchpipe);
chdir $cwd or die "Unable to restore working directory: $!"; # Restore
- $rstat =($? >> 8);
+ my $rstat =($? >> 8);
if ($rstat) {
warn "Patching failed (exit code $rstat), aborting\n";
return;
diff --git a/apt-cacher-lib-cs.pl b/apt-cacher-lib-cs.pl
index a8746b5..12a6430 100755
--- a/apt-cacher-lib-cs.pl
+++ b/apt-cacher-lib-cs.pl
@@ -196,9 +196,10 @@ sub import_sums {
my $dbh=${$_[1]};
my %temp;
return unless $cfg->{checksum};
- extract_sums($_[0],\%temp);
- while (my ($filename,$data) = each %temp){
- $dbh->db_put($filename,$data) and warn "db_put $filename, $data failed
with $!" ;
+ if (extract_sums($_[0],\%temp)) {
+ while (my ($filename,$data) = each %temp){
+ $dbh->db_put($filename,$data) and warn "db_put $filename, $data
failed with $!" ;
+ }
}
}
diff --git a/apt-cacher-lib.pl b/apt-cacher-lib.pl
index 163b14a..b258a7f 100755
--- a/apt-cacher-lib.pl
+++ b/apt-cacher-lib.pl
@@ -227,6 +227,7 @@ sub extract_sums {
my ($file,$complete,$sha1,$sha256,$md5,$size);
while(<$raw>) {
+ last if $AnyUncompressError;
if(/^\s(\w{40})\s+(\d+)\s(\S+)\n/ && $indexbase) { # diff_Index/Release
SHA1
$sha1=$1;
$size =$2;
@@ -284,6 +285,10 @@ sub extract_sums {
}
}
};
+ if ($AnyUncompressError) {
+ warn "$name Read failed: $AnyUncompressError. Aborting read\n";
+ return;
+ }
return 1;
}
Mark
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]