From 1f12544179041b151f146fbb604e9af165ffe379 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Mon, 3 Aug 2020 19:05:29 +0100 Subject: refactor(3p/nix): Build nix-daemon as a separate binary Skips over all the monobinary stuff and moves to a separate binary for nix-daemon. This also replaces the flag parsing logic with absl::flags. This causes a behaviour change for --help, which no longer tries to display a man page but instead shows the actual command-line help. Note: This binary no longer links to the Boehm GC. Change-Id: Ib852e994b82f2d56e91262878c10650e656427a9 Reviewed-on: https://cl.tvl.fyi/c/depot/+/1622 Tested-by: BuildkiteCI Reviewed-by: glittershark --- third_party/nix/default.nix | 1 - third_party/nix/src/CMakeLists.txt | 3 +- third_party/nix/src/nix-daemon/CMakeLists.txt | 26 ++++ third_party/nix/src/nix-daemon/nix-daemon-main.cc | 143 ---------------------- third_party/nix/src/nix-daemon/nix-daemon.cc | 131 ++++++++++++++++++++ 5 files changed, 158 insertions(+), 146 deletions(-) create mode 100644 third_party/nix/src/nix-daemon/CMakeLists.txt delete mode 100644 third_party/nix/src/nix-daemon/nix-daemon-main.cc create mode 100644 third_party/nix/src/nix-daemon/nix-daemon.cc (limited to 'third_party') diff --git a/third_party/nix/default.nix b/third_party/nix/default.nix index adb1bd33d1ec..96c5c250e40d 100644 --- a/third_party/nix/default.nix +++ b/third_party/nix/default.nix @@ -121,7 +121,6 @@ in lib.fix (self: pkgs.llvmPackages.libcxxStdenv.mkDerivation { ln -s $out/bin/nix $out/bin/nix-channel ln -s $out/bin/nix $out/bin/nix-collect-garbage ln -s $out/bin/nix $out/bin/nix-copy-closure - ln -s $out/bin/nix $out/bin/nix-daemon ln -s $out/bin/nix $out/bin/nix-env ln -s $out/bin/nix $out/bin/nix-hash ln -s $out/bin/nix $out/bin/nix-instantiate diff --git a/third_party/nix/src/CMakeLists.txt b/third_party/nix/src/CMakeLists.txt index a142bfafb463..486c69fa2a3c 100644 --- a/third_party/nix/src/CMakeLists.txt +++ b/third_party/nix/src/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(libutil) add_subdirectory(libstore) add_subdirectory(libmain) add_subdirectory(libexpr) +add_subdirectory(nix-daemon) if (PACKAGE_TESTS) add_subdirectory(tests) @@ -61,8 +62,6 @@ target_sources(nix nix-channel/nix-channel.cc nix-collect-garbage/nix-collect-garbage.cc nix-copy-closure/nix-copy-closure.cc - nix-daemon/nix-daemon-proto.cc - nix-daemon/nix-daemon-main.cc nix-env/nix-env.cc nix-env/user-env.cc nix-instantiate/nix-instantiate.cc diff --git a/third_party/nix/src/nix-daemon/CMakeLists.txt b/third_party/nix/src/nix-daemon/CMakeLists.txt new file mode 100644 index 000000000000..27a4a1254e77 --- /dev/null +++ b/third_party/nix/src/nix-daemon/CMakeLists.txt @@ -0,0 +1,26 @@ +# -*- mode: cmake; -*- + +# The nix-daemon is the binary running the gRPC server component to +# which other components of Nix talk to perform store and builder +# operations. + +add_executable(nix-daemon) +include_directories(${PROJECT_BINARY_DIR}) # for config.h +set_property(TARGET nix-daemon PROPERTY CXX_STANDARD 17) + +target_sources(nix-daemon + PRIVATE + nix-daemon-proto.hh + nix-daemon-proto.cc + nix-daemon.cc +) + +target_link_libraries(nix-daemon + nixutil + nixstore + nixmain + absl::flags + absl::flags_parse +) + +install(TARGETS nix-daemon DESTINATION bin) diff --git a/third_party/nix/src/nix-daemon/nix-daemon-main.cc b/third_party/nix/src/nix-daemon/nix-daemon-main.cc deleted file mode 100644 index e492c343b900..000000000000 --- a/third_party/nix/src/nix-daemon/nix-daemon-main.cc +++ /dev/null @@ -1,143 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmain/shared.hh" -#include "libstore/globals.hh" -#include "libstore/store-api.hh" -#include "libutil/util.hh" -#include "nix-daemon-proto.hh" -#include "nix-daemon/nix-daemon-proto.hh" -#include "nix/legacy.hh" - -namespace nix::daemon { - -using grpc::Server; -using grpc_impl::ServerBuilder; - -// TODO(grfn): There has to be a better way to do this - this was ported -// verbatim from the old daemon implementation without much critical evaluation. -static int ForwardToSocket(nix::Path socket_path) { - // Forward on this connection to the real daemon - int sockfd = socket(PF_UNIX, SOCK_STREAM, 0); - if (sockfd == -1) { - throw SysError("creating Unix domain socket"); - } - - auto socketDir = dirOf(socket_path); - if (chdir(socketDir.c_str()) == -1) { - throw SysError(format("changing to socket directory '%1%'") % socketDir); - } - - auto socketName = baseNameOf(socket_path); - auto addr = sockaddr_un{}; - addr.sun_family = AF_UNIX; - if (socketName.size() + 1 >= sizeof(addr.sun_path)) { - throw Error(format("socket name %1% is too long") % socketName); - } - strncpy(addr.sun_path, socketName.c_str(), sizeof(addr.sun_family)); - - if (connect(sockfd, reinterpret_cast(&addr), - sizeof(addr)) == -1) { - throw SysError(format("cannot connect to daemon at %1%") % socket_path); - } - - auto nfds = (sockfd > STDIN_FILENO ? sockfd : STDIN_FILENO) + 1; - while (true) { - fd_set fds; - FD_ZERO(&fds); - FD_SET(sockfd, &fds); - FD_SET(STDIN_FILENO, &fds); - if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1) { - throw SysError("waiting for data from client or server"); - } - if (FD_ISSET(sockfd, &fds)) { - auto res = splice(sockfd, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, - SPLICE_F_MOVE); - if (res == -1) { - throw SysError("splicing data from daemon socket to stdout"); - } - if (res == 0) { - throw EndOfFile("unexpected EOF from daemon socket"); - } - } - if (FD_ISSET(STDIN_FILENO, &fds)) { - auto res = splice(STDIN_FILENO, nullptr, sockfd, nullptr, SSIZE_MAX, - SPLICE_F_MOVE); - if (res == -1) { - throw SysError("splicing data from stdin to daemon socket"); - } - if (res == 0) { - return 0; - } - } - } -} - -int RunServer() { - Store::Params params; - params["path-info-cache-size"] = "0"; - auto store = openStore(settings.storeUri, params); - auto worker = NewWorkerService(*store); - - std::filesystem::path socket_path(settings.nixDaemonSocketFile); - std::filesystem::create_directories(socket_path.parent_path()); - auto socket_addr = absl::StrFormat("unix://%s", socket_path); - - ServerBuilder builder; - builder.AddListeningPort(socket_addr, grpc::InsecureServerCredentials()); - builder.RegisterService(worker); - - std::unique_ptr server(builder.BuildAndStart()); - if (server) { - LOG(INFO) << "Nix daemon listening at " << socket_addr; - server->Wait(); - return 0; - } else { - return 1; - } -} - -static int main_(int argc, char** argv) { - auto pipe = false; - - // TODO(grfn): Replace with absl::flags - parseCmdLine(argc, argv, - [&](Strings::iterator& arg, const Strings::iterator& end) { - if (*arg == "--help") { - showManPage("nix-daemon"); - } else if (*arg == "--version") { - printVersion("nix-daemon"); - } else if (*arg == "--pipe") { - // Causes the daemon to forward stdin and stdout to and from - // the actual daemon socket - pipe = true; - } else { - return false; - } - return true; - }); - - if (pipe) { - if (getStoreType() == tDaemon) { - return ForwardToSocket(settings.nixDaemonSocketFile); - } else { - // TODO(grfn): Need to launch a server on stdin here - upstream calls - // processConnection(true, "root", 0); - throw "Not implemented"; - } - } - return RunServer(); -} - -// TODO(grfn): Replace this with something less magical -static RegisterLegacyCommand s1("nix-daemon", main_); - -} // namespace nix::daemon diff --git a/third_party/nix/src/nix-daemon/nix-daemon.cc b/third_party/nix/src/nix-daemon/nix-daemon.cc new file mode 100644 index 000000000000..02b350c3d87b --- /dev/null +++ b/third_party/nix/src/nix-daemon/nix-daemon.cc @@ -0,0 +1,131 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libmain/shared.hh" // TODO(tazjin): can this be removed? +#include "libstore/globals.hh" +#include "libstore/store-api.hh" +#include "libutil/util.hh" +#include "nix-daemon-proto.hh" +#include "nix-daemon/nix-daemon-proto.hh" +#include "nix/legacy.hh" + +ABSL_FLAG(bool, pipe, false, "Use pipes for daemon communication"); + +namespace nix::daemon { + +using grpc::Server; +using grpc_impl::ServerBuilder; + +// TODO(grfn): There has to be a better way to do this - this was ported +// verbatim from the old daemon implementation without much critical evaluation. +static int ForwardToSocket(nix::Path socket_path) { + // Forward on this connection to the real daemon + int sockfd = socket(PF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) { + throw SysError("creating Unix domain socket"); + } + + auto socketDir = dirOf(socket_path); + if (chdir(socketDir.c_str()) == -1) { + throw SysError(format("changing to socket directory '%1%'") % socketDir); + } + + auto socketName = baseNameOf(socket_path); + auto addr = sockaddr_un{}; + addr.sun_family = AF_UNIX; + if (socketName.size() + 1 >= sizeof(addr.sun_path)) { + throw Error(format("socket name %1% is too long") % socketName); + } + strncpy(addr.sun_path, socketName.c_str(), sizeof(addr.sun_family)); + + if (connect(sockfd, reinterpret_cast(&addr), + sizeof(addr)) == -1) { + throw SysError(format("cannot connect to daemon at %1%") % socket_path); + } + + auto nfds = (sockfd > STDIN_FILENO ? sockfd : STDIN_FILENO) + 1; + while (true) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(sockfd, &fds); + FD_SET(STDIN_FILENO, &fds); + if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1) { + throw SysError("waiting for data from client or server"); + } + if (FD_ISSET(sockfd, &fds)) { + auto res = splice(sockfd, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, + SPLICE_F_MOVE); + if (res == -1) { + throw SysError("splicing data from daemon socket to stdout"); + } + if (res == 0) { + throw EndOfFile("unexpected EOF from daemon socket"); + } + } + if (FD_ISSET(STDIN_FILENO, &fds)) { + auto res = splice(STDIN_FILENO, nullptr, sockfd, nullptr, SSIZE_MAX, + SPLICE_F_MOVE); + if (res == -1) { + throw SysError("splicing data from stdin to daemon socket"); + } + if (res == 0) { + return 0; + } + } + } +} + +int RunServer() { + Store::Params params; + params["path-info-cache-size"] = "0"; + auto store = openStore(settings.storeUri, params); + auto worker = NewWorkerService(*store); + + std::filesystem::path socket_path(settings.nixDaemonSocketFile); + std::filesystem::create_directories(socket_path.parent_path()); + auto socket_addr = absl::StrFormat("unix://%s", socket_path); + + ServerBuilder builder; + builder.AddListeningPort(socket_addr, grpc::InsecureServerCredentials()); + builder.RegisterService(worker); + + std::unique_ptr server(builder.BuildAndStart()); + if (server) { + LOG(INFO) << "Nix daemon listening at " << socket_addr; + server->Wait(); + return 0; + } else { + return 1; + } +} + +} // namespace nix::daemon + +int main(int argc, char** argv) { + absl::SetFlagsUsageConfig({.version_string = [] { return nix::nixVersion; }}); + absl::ParseCommandLine(argc, argv); + + if (absl::GetFlag(FLAGS_pipe)) { + if (nix::getStoreType() == nix::tDaemon) { + return nix::daemon::ForwardToSocket(nix::settings.nixDaemonSocketFile); + } else { + // TODO(grfn): Need to launch a server on stdin here - upstream calls + // processConnection(true, "root", 0); + LOG(ERROR) << "not implemented"; + return 1; + } + } + + return nix::daemon::RunServer(); +} -- cgit 1.4.1