aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-06-18 23:01:46 -0400
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-06-18 23:01:46 -0400
commit2f3f413e91620d2314be59870f4bd67292f7d2de (patch)
treef2c9fce2695e56473662ee579c75f8d57d7cf779 /src
parent02fb6323e06502e410dd5d5f8fe10589a7c938d4 (diff)
Support socket-based, on-demand activation of the Nix daemon with systemd
Systemd can start the Nix daemon on demand when the Nix daemon socket is first accessed. This is signalled through the LISTEN_FDS environment variable, so all we need to do is check for that and then use file descriptor 3 as the listen socket instead of creating one ourselves.
Diffstat (limited to 'src')
-rw-r--r--src/nix-worker/nix-worker.cc76
1 files changed, 46 insertions, 30 deletions
diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc
index b7bce20bd..6131e73e6 100644
--- a/src/nix-worker/nix-worker.cc
+++ b/src/nix-worker/nix-worker.cc
@@ -695,51 +695,67 @@ static void setSigChldAction(bool autoReap)
}
+#define SD_LISTEN_FDS_START 3
+
+
static void daemonLoop()
{
/* Get rid of children automatically; don't let them become
zombies. */
setSigChldAction(true);
-
- /* Create and bind to a Unix domain socket. */
- AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM, 0);
- if (fdSocket == -1)
- throw SysError("cannot create Unix domain socket");
- closeOnExec(fdSocket);
+ AutoCloseFD fdSocket;
+
+ /* Handle socket-based activation by systemd. */
+ if (getEnv("LISTEN_FDS") != "") {
+ if (getEnv("LISTEN_PID") != int2String(getpid()) || getEnv("LISTEN_FDS") != "1")
+ throw Error("unexpected systemd environment variables");
+ fdSocket = SD_LISTEN_FDS_START;
+ }
+
+ /* Otherwise, create and bind to a Unix domain socket. */
+ else {
- string socketPath = nixStateDir + DEFAULT_SOCKET_PATH;
+ /* Create and bind to a Unix domain socket. */
+ fdSocket = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fdSocket == -1)
+ throw SysError("cannot create Unix domain socket");
+
+ string socketPath = nixStateDir + DEFAULT_SOCKET_PATH;
- createDirs(dirOf(socketPath));
+ createDirs(dirOf(socketPath));
- /* Urgh, sockaddr_un allows path names of only 108 characters. So
- chdir to the socket directory so that we can pass a relative
- path name. */
- chdir(dirOf(socketPath).c_str());
- Path socketPathRel = "./" + baseNameOf(socketPath);
+ /* Urgh, sockaddr_un allows path names of only 108 characters.
+ So chdir to the socket directory so that we can pass a
+ relative path name. */
+ chdir(dirOf(socketPath).c_str());
+ Path socketPathRel = "./" + baseNameOf(socketPath);
- struct sockaddr_un addr;
- addr.sun_family = AF_UNIX;
- if (socketPathRel.size() >= sizeof(addr.sun_path))
- throw Error(format("socket path `%1%' is too long") % socketPathRel);
- strcpy(addr.sun_path, socketPathRel.c_str());
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ if (socketPathRel.size() >= sizeof(addr.sun_path))
+ throw Error(format("socket path `%1%' is too long") % socketPathRel);
+ strcpy(addr.sun_path, socketPathRel.c_str());
- unlink(socketPath.c_str());
+ unlink(socketPath.c_str());
- /* Make sure that the socket is created with 0666 permission
- (everybody can connect --- provided they have access to the
- directory containing the socket). */
- mode_t oldMode = umask(0111);
- int res = bind(fdSocket, (struct sockaddr *) &addr, sizeof(addr));
- umask(oldMode);
- if (res == -1)
- throw SysError(format("cannot bind to socket `%1%'") % socketPath);
+ /* Make sure that the socket is created with 0666 permission
+ (everybody can connect --- provided they have access to the
+ directory containing the socket). */
+ mode_t oldMode = umask(0111);
+ int res = bind(fdSocket, (struct sockaddr *) &addr, sizeof(addr));
+ umask(oldMode);
+ if (res == -1)
+ throw SysError(format("cannot bind to socket `%1%'") % socketPath);
- chdir("/"); /* back to the root */
+ chdir("/"); /* back to the root */
- if (listen(fdSocket, 5) == -1)
- throw SysError(format("cannot listen on socket `%1%'") % socketPath);
+ if (listen(fdSocket, 5) == -1)
+ throw SysError(format("cannot listen on socket `%1%'") % socketPath);
+ }
+ closeOnExec(fdSocket);
+
/* Loop accepting connections. */
while (1) {