diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2021-12-13 19:55:32 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-13 19:55:32 +0100 |
commit | 6ae5f39ea07f67b0dc746860ddf25e5659c94d81 (patch) | |
tree | c0e81edcdf789db71428024a4ca1176499b33ce7 | |
parent | e2e5f3a78f31e4e72170ebfe48cbbb082860cc24 (diff) | |
parent | d17d46cfc2e38efb63565270a1fba7b03b37de16 (diff) |
Merge pull request #5770 from edolstra/gc-fixes
Fix macOS GC failures
-rw-r--r-- | src/libstore/gc.cc | 25 | ||||
-rw-r--r-- | tests/gc-non-blocking.sh | 2 |
2 files changed, 24 insertions, 3 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 7a414da6b..e35199b3d 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -126,7 +126,17 @@ void LocalStore::addTempRoot(const StorePath & path) auto socketPath = stateDir.get() + gcSocketPath; debug("connecting to '%s'", socketPath); state->fdRootsSocket = createUnixDomainSocket(); - nix::connect(state->fdRootsSocket.get(), socketPath); + try { + nix::connect(state->fdRootsSocket.get(), socketPath); + } catch (SysError & e) { + /* The garbage collector may have exited, so we need to + restart. */ + if (e.errNo == ECONNREFUSED) { + debug("GC socket connection refused"); + state->fdRootsSocket.close(); + goto restart; + } + } } try { @@ -523,6 +533,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) AutoCloseFD fdClient = accept(fdServer.get(), nullptr, nullptr); if (!fdClient) continue; + debug("GC roots server accepted new client"); + /* Process the connection in a separate thread. */ auto fdClient_ = fdClient.get(); std::thread clientThread([&, fdClient = std::move(fdClient)]() { @@ -535,6 +547,12 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } }); + /* On macOS, accepted sockets inherit the + non-blocking flag from the server socket, so + explicitly make it blocking. */ + if (fcntl(fdServer.get(), F_SETFL, fcntl(fdServer.get(), F_GETFL) & ~O_NONBLOCK) == -1) + abort(); + while (true) { try { auto path = readLine(fdClient.get()); @@ -559,7 +577,10 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } else printError("received garbage instead of a root from client"); writeFull(fdClient.get(), "1", false); - } catch (Error &) { break; } + } catch (Error & e) { + debug("reading GC root from client: %s", e.msg()); + break; + } } }); diff --git a/tests/gc-non-blocking.sh b/tests/gc-non-blocking.sh index 8b21c6f1c..0d781485d 100644 --- a/tests/gc-non-blocking.sh +++ b/tests/gc-non-blocking.sh @@ -19,7 +19,7 @@ pid=$! sleep 2 -outPath=$(nix-build -o "$TEST_ROOT/result" -E " +outPath=$(nix-build --max-silent-time 60 -o "$TEST_ROOT/result" -E " with import ./config.nix; mkDerivation { name = \"non-blocking\"; |