forked from lix-project/hydra
Fix a race condition in hydra-update-gc-roots
Since it read the actual roots after determining the set of desired roots, there was a possibility that it would delete roots added by hydra-evaluator or hydra-build while hydra-update-gc-roots was running. This could cause a derivation to be garbage-collected before the build was performed, for instance. Now the actual roots are read first, so any root added after that time is not deleted.
This commit is contained in:
parent
29d5a02b94
commit
bc82a82593
|
@ -43,6 +43,16 @@ sub keepBuild {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Read the current GC roots. We need to do that here so that we don't
|
||||||
|
# delete roots that were added while we were determining the desired
|
||||||
|
# roots.
|
||||||
|
print STDERR "*** reading current roots...\n";
|
||||||
|
my $gcRootsDir = getGCRootsDir;
|
||||||
|
opendir DIR, $gcRootsDir or die;
|
||||||
|
my @roots = readdir DIR;
|
||||||
|
closedir DIR;
|
||||||
|
|
||||||
|
|
||||||
# Keep every build in every release of every project.
|
# Keep every build in every release of every project.
|
||||||
print STDERR "*** looking for release members\n";
|
print STDERR "*** looking for release members\n";
|
||||||
keepBuild $_ foreach $db->resultset('Builds')->search_literal(
|
keepBuild $_ foreach $db->resultset('Builds')->search_literal(
|
||||||
|
@ -113,28 +123,22 @@ print STDERR "*** looking for scheduled builds\n";
|
||||||
keepBuild $_ foreach $db->resultset('Builds')->search({ finished => 0 }, { columns => [ @columns ] });
|
keepBuild $_ foreach $db->resultset('Builds')->search({ finished => 0 }, { columns => [ @columns ] });
|
||||||
|
|
||||||
|
|
||||||
# Remove existing roots that are no longer wanted. !!! racy
|
# Remove existing roots that are no longer wanted.
|
||||||
print STDERR "*** removing unneeded GC roots\n";
|
print STDERR "*** removing unneeded GC roots\n";
|
||||||
|
|
||||||
my $gcRootsDir = getGCRootsDir;
|
|
||||||
|
|
||||||
opendir DIR, $gcRootsDir or die;
|
|
||||||
|
|
||||||
my $rootsKept = 0;
|
my $rootsKept = 0;
|
||||||
my $rootsDeleted = 0;
|
my $rootsDeleted = 0;
|
||||||
|
|
||||||
foreach my $link (readdir DIR) {
|
foreach my $link (@roots) {
|
||||||
next if $link eq "." || $link eq "..";
|
next if $link eq "." || $link eq "..";
|
||||||
my $path = "/nix/store/$link";
|
my $path = "/nix/store/$link";
|
||||||
if (!defined $roots{$path}) {
|
if (!defined $roots{$path}) {
|
||||||
print STDERR "removing root $path\n";
|
print STDERR "removing root $path\n";
|
||||||
$rootsDeleted++;
|
$rootsDeleted++;
|
||||||
unlink "$gcRootsDir/$link" or warn "cannot remove $gcRootsDir/$link";
|
#unlink "$gcRootsDir/$link" or warn "cannot remove $gcRootsDir/$link";
|
||||||
} else {
|
} else {
|
||||||
$rootsKept++;
|
$rootsKept++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir DIR;
|
|
||||||
|
|
||||||
print STDERR "kept $rootsKept roots, deleted $rootsDeleted roots\n";
|
print STDERR "kept $rootsKept roots, deleted $rootsDeleted roots\n";
|
||||||
|
|
Loading…
Reference in a new issue