aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build
diff options
context:
space:
mode:
authorMoritz Angermann <moritz.angermann@gmail.com>2023-04-05 17:05:17 +0800
committerMoritz Angermann <moritz.angermann@gmail.com>2023-04-25 09:39:05 +0800
commit0e18254aa81b9315c13d6ae736cb38666d19f122 (patch)
tree60ed347dd4cbebd48cb7cb1dc9d4d34416f2d132 /src/libstore/build
parentef432b2b1502c73d505d8fdb487db529601fa4ab (diff)
Fix shutdown behavior and resource management for recursive-nix on macOS
Previously, we relied on the `shutdown()` function to terminate `accept()` calls on a listening socket. However, this approach did not work on macOS as the waiting `accept()` call is not considered a connected socket, resulting in an `ENOTCONN` error. Instead, we now close the listening socket to terminate the `accept()` call. Additionally, we fixed a resource management issue where we set the `daemonSocket` variable to -1, triggering resource cleanup and causing the `stopDaemon` function to be called twice. This resulted in errors as the socket was already closed by the time the second `stopDaemon` call was made. Instead of setting `daemonSocket` to -1, we now release the socket using the `release()` method on a unique pointer. This properly transfers ownership and allows for correct resource cleanup. These changes ensure proper behavior and resource management for the recursive-nix feature on macOS.
Diffstat (limited to 'src/libstore/build')
-rw-r--r--src/libstore/build/local-derivation-goal.cc23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 21cd6e7ee..4b978f2a4 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -1457,7 +1457,7 @@ void LocalDerivationGoal::startDaemon()
(struct sockaddr *) &remoteAddr, &remoteAddrLen);
if (!remote) {
if (errno == EINTR || errno == EAGAIN) continue;
- if (errno == EINVAL) break;
+ if (errno == EINVAL || errno == ECONNABORTED) break;
throw SysError("accepting connection");
}
@@ -1487,8 +1487,22 @@ void LocalDerivationGoal::startDaemon()
void LocalDerivationGoal::stopDaemon()
{
- if (daemonSocket && shutdown(daemonSocket.get(), SHUT_RDWR) == -1)
- throw SysError("shutting down daemon socket");
+ if (daemonSocket && shutdown(daemonSocket.get(), SHUT_RDWR) == -1) {
+ // According to the POSIX standard, the 'shutdown' function should
+ // return an ENOTCONN error when attempting to shut down a socket that
+ // hasn't been connected yet. This situation occurs when the 'accept'
+ // function is called on a socket without any accepted connections,
+ // leaving the socket unconnected. While Linux doesn't seem to produce
+ // an error for sockets that have only been accepted, more
+ // POSIX-compliant operating systems like OpenBSD, macOS, and others do
+ // return the ENOTCONN error. Therefore, we handle this error here to
+ // avoid raising an exception for compliant behaviour.
+ if (errno == ENOTCONN) {
+ daemonSocket.close();
+ } else {
+ throw SysError("shutting down daemon socket");
+ }
+ }
if (daemonThread.joinable())
daemonThread.join();
@@ -1499,7 +1513,8 @@ void LocalDerivationGoal::stopDaemon()
thread.join();
daemonWorkerThreads.clear();
- daemonSocket = -1;
+ // release the socket.
+ daemonSocket.close();
}