main
patch 37 lines 1.83 KB
Raw
1 diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
2 index 16b81abf2..d3c46ae8d 100644
3 --- a/src/libstore/gc.cc
4 +++ b/src/libstore/gc.cc
5 @@ -680,6 +680,32 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
6 if (!dead.insert(path).second)
7 continue;
8 if (shouldDelete) {
9 + /* Re-check tempRoots before deleting and set pending
10 + to synchronise with addTempRoot. Between the BFS
11 + and this deletion loop, new temproots may have been
12 + added via the GC socket by a concurrent process
13 + (e.g. an evaluator calling addTempRoot). The BFS
14 + only checks tempRoots when it first visits a path,
15 + but the "pending" mechanism only blocks the socket
16 + handler for the single path currently being visited,
17 + not for paths already queued for deletion. */
18 + {
19 + auto hashPart = std::string(path.hashPart());
20 + auto shared(_shared.lock());
21 + if (shared->tempRoots.count(hashPart)) {
22 + debug(
23 + "not deleting '%s' because it became a temporary root after initial scan",
24 + printStorePath(path));
25 + alive.insert(path);
26 + continue;
27 + }
28 + shared->pending = hashPart;
29 + }
30 + Finally resetPending([&]() {
31 + auto shared(_shared.lock());
32 + shared->pending.reset();
33 + wakeup.notify_all();
34 + });
35 try {
36 invalidatePathChecked(path);
37 deleteFromStore(path.to_string(), true);