From d97b9f138c173983429bfd0c92e78670d70c0190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophane=20Hufschmitt?= Date: Mon, 11 Apr 2022 10:20:36 +0200 Subject: [PATCH] nix-find-roots: Support systemd socket activation --- src/nix-find-roots/main.cc | 39 ++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/nix-find-roots/main.cc b/src/nix-find-roots/main.cc index d93e7eee7..0d8186a04 100644 --- a/src/nix-find-roots/main.cc +++ b/src/nix-find-roots/main.cc @@ -68,6 +68,7 @@ TracerConfig parseCmdLine(int argc, char** argv) }; } +#define SD_LISTEN_FDS_START 3 // Like in systemd int main(int argc, char * * argv) { @@ -77,23 +78,33 @@ int main(int argc, char * * argv) opts.stateDir / fs::path("gcroots"), }; - int mySock = socket(PF_UNIX, SOCK_STREAM, 0); - if (mySock == 0) { - throw Error("Cannot create Unix domain socket"); - } - struct sockaddr_un addr; - addr.sun_family = AF_UNIX; + int mySock; - unlink(opts.socketPath.c_str()); - strcpy(addr.sun_path, opts.socketPath.c_str()); - if (bind(mySock, (struct sockaddr*) &addr, sizeof(addr)) == -1) { - throw Error("Cannot bind to socket"); + // Handle socket-based activation by systemd. + auto rawListenFds = std::getenv("LISTEN_FDS"); + if (rawListenFds) { + auto listenFds = std::string(rawListenFds); + if (std::getenv("LISTEN_PID") != std::to_string(getpid()) || listenFds != "1") + throw Error("unexpected systemd environment variables"); + mySock = SD_LISTEN_FDS_START; + } else { + mySock = socket(PF_UNIX, SOCK_STREAM, 0); + if (mySock == 0) { + throw Error("Cannot create Unix domain socket"); + } + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + + unlink(opts.socketPath.c_str()); + strcpy(addr.sun_path, opts.socketPath.c_str()); + if (bind(mySock, (struct sockaddr*) &addr, sizeof(addr)) == -1) { + throw Error("Cannot bind to socket"); + } + + if (listen(mySock, 5) == -1) + throw Error("cannot listen on socket " + opts.socketPath.string()); } - if (listen(mySock, 5) == -1) - throw Error("cannot listen on socket " + opts.socketPath.string()); - - addr.sun_family = AF_UNIX; while (1) { struct sockaddr_un remoteAddr; socklen_t remoteAddrLen = sizeof(remoteAddr);