fix(gc): log sudden "path in use" exceptions and recover during GC gracefully

Original-Author: picnoir <picnoir@alternativebit.fr>

Inspired from
https://github.com/NixOS/nix/pull/11922/commits/ced8d311a593fcf9c3823e4e118474ac132d8e60
and adapted for Lix needs.

TL;DR: The topological sort should ensure that it is possible to delete
the path iterated upon. Nonetheless, in some cases,
`invalidatePathChecked` can still throw `PathInUse`, the exception
bubbles up and cancel the garbage collection procedure, leaving the rest
of the paths untouched. This change ensure that the error is logged for
further investigation but doesn't prevent the GC to continue when it
can.

After code review, we decided to make it a `printInfo` to inform the
user about sudden "in use" dependencies during garbage collection and
let them re-run garbage collection if they care about this.

References: https://github.com/NixOS/nix/issues/11923
References: https://git.lix.systems/lix-project/lix/issues/621
Change-Id: I5606c9afd16b5faa747b713fde2dc24016990ba3
Signed-off-by: Raito Bezarius <raito@lix.systems>
(cherry picked from commit 6a41dae49a)
This commit is contained in:
Raito Bezarius
2025-01-23 06:04:00 +00:00
committed by jade
parent 8e2ab5532c
commit 50def3fa73
+10 -3
View File
@@ -746,9 +746,16 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
for (auto & path : topoSortPaths(visited)) {
if (!dead.insert(path).second) continue;
if (shouldDelete) {
invalidatePathChecked(path);
deleteFromStore(path.to_string());
referrersCache.erase(path);
try {
invalidatePathChecked(path);
deleteFromStore(path.to_string());
referrersCache.erase(path);
} catch (PathInUse &) {
// References to upstream "bugs":
// https://github.com/NixOS/nix/issues/11923
// https://git.lix.systems/lix-project/lix/issues/621
printInfo("Skipping deletion of path '%1%' because it is now in use, preventing its removal.", printStorePath(path));
}
}
}
};