Merge pull request #5335 from edolstra/socket-paths
Support arbitrary-length socket paths
This commit is contained in:
commit
fd57e7074f
15
flake.nix
15
flake.nix
|
@ -126,8 +126,7 @@
|
|||
''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
# Converts /nix/store/50p3qk8kka9dl6wyq40vydq945k0j3kv-nix-2.4pre20201102_550e11f/bin/nix
|
||||
# To 50p3qk8kka9dl6wyq40vydq945k0j3kv/bin/nix
|
||||
# Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix.
|
||||
tarballPath() {
|
||||
# Remove the store prefix
|
||||
local path=''${1#${builtins.storeDir}/}
|
||||
|
@ -153,13 +152,15 @@
|
|||
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
testNixVersions = pkgs: client: daemon: with commonDeps pkgs; pkgs.stdenv.mkDerivation {
|
||||
testNixVersions = pkgs: client: daemon: with commonDeps pkgs; with pkgs.lib; pkgs.stdenv.mkDerivation {
|
||||
NIX_DAEMON_PACKAGE = daemon;
|
||||
NIX_CLIENT_PACKAGE = client;
|
||||
# Must keep this name short as OSX has a rather strict limit on the
|
||||
# socket path length, and this name appears in the path of the
|
||||
# nix-daemon socket used in the tests
|
||||
name = "nix-tests";
|
||||
name =
|
||||
"nix-tests"
|
||||
+ optionalString
|
||||
(versionAtLeast daemon.version "2.4pre20211005" &&
|
||||
versionAtLeast client.version "2.4pre20211005")
|
||||
"-${client.version}-against-${daemon.version}";
|
||||
inherit version;
|
||||
|
||||
src = self;
|
||||
|
|
|
@ -65,16 +65,7 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
|
|||
throw SysError("cannot create Unix domain socket");
|
||||
closeOnExec(conn->fd.get());
|
||||
|
||||
string socketPath = path ? *path : settings.nixDaemonSocketFile;
|
||||
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (socketPath.size() + 1 >= sizeof(addr.sun_path))
|
||||
throw Error("socket path '%1%' is too long", socketPath);
|
||||
strcpy(addr.sun_path, socketPath.c_str());
|
||||
|
||||
if (::connect(conn->fd.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
throw SysError("cannot connect to daemon at '%1%'", socketPath);
|
||||
nix::connect(conn->fd.get(), path ? *path : settings.nixDaemonSocketFile);
|
||||
|
||||
conn->from.fd = conn->fd.get();
|
||||
conn->to.fd = conn->fd.get();
|
||||
|
|
|
@ -903,7 +903,7 @@ int Pid::wait()
|
|||
return status;
|
||||
}
|
||||
if (errno != EINTR)
|
||||
throw SysError("cannot get child exit status");
|
||||
throw SysError("cannot get exit status of PID %d", pid);
|
||||
checkInterrupt();
|
||||
}
|
||||
}
|
||||
|
@ -1686,16 +1686,7 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
|
|||
|
||||
closeOnExec(fdSocket.get());
|
||||
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (path.size() + 1 >= sizeof(addr.sun_path))
|
||||
throw Error("socket path '%1%' is too long", path);
|
||||
strcpy(addr.sun_path, path.c_str());
|
||||
|
||||
unlink(path.c_str());
|
||||
|
||||
if (bind(fdSocket.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
throw SysError("cannot bind to socket '%1%'", path);
|
||||
bind(fdSocket.get(), path);
|
||||
|
||||
if (chmod(path.c_str(), mode) == -1)
|
||||
throw SysError("changing permissions on '%1%'", path);
|
||||
|
@ -1707,6 +1698,66 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
|
|||
}
|
||||
|
||||
|
||||
void bind(int fd, const std::string & path)
|
||||
{
|
||||
unlink(path.c_str());
|
||||
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
||||
Pid pid = startProcess([&]() {
|
||||
auto dir = dirOf(path);
|
||||
if (chdir(dir.c_str()) == -1)
|
||||
throw SysError("chdir to '%s' failed", dir);
|
||||
std::string base(baseNameOf(path));
|
||||
if (base.size() + 1 >= sizeof(addr.sun_path))
|
||||
throw Error("socket path '%s' is too long", base);
|
||||
strcpy(addr.sun_path, base.c_str());
|
||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
throw SysError("cannot bind to socket '%s'", path);
|
||||
_exit(0);
|
||||
});
|
||||
int status = pid.wait();
|
||||
if (status != 0)
|
||||
throw Error("cannot bind to socket '%s'", path);
|
||||
} else {
|
||||
strcpy(addr.sun_path, path.c_str());
|
||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
throw SysError("cannot bind to socket '%s'", path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void connect(int fd, const std::string & path)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
||||
Pid pid = startProcess([&]() {
|
||||
auto dir = dirOf(path);
|
||||
if (chdir(dir.c_str()) == -1)
|
||||
throw SysError("chdir to '%s' failed", dir);
|
||||
std::string base(baseNameOf(path));
|
||||
if (base.size() + 1 >= sizeof(addr.sun_path))
|
||||
throw Error("socket path '%s' is too long", base);
|
||||
strcpy(addr.sun_path, base.c_str());
|
||||
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
throw SysError("cannot connect to socket at '%s'", path);
|
||||
_exit(0);
|
||||
});
|
||||
int status = pid.wait();
|
||||
if (status != 0)
|
||||
throw Error("cannot connect to socket at '%s'", path);
|
||||
} else {
|
||||
strcpy(addr.sun_path, path.c_str());
|
||||
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
throw SysError("cannot connect to socket at '%s'", path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string showBytes(uint64_t bytes)
|
||||
{
|
||||
return fmt("%.2f MiB", bytes / (1024.0 * 1024.0));
|
||||
|
|
|
@ -259,7 +259,7 @@ void killUser(uid_t uid);
|
|||
pid to the caller. */
|
||||
struct ProcessOptions
|
||||
{
|
||||
string errorPrefix = "error: ";
|
||||
string errorPrefix = "";
|
||||
bool dieWithParent = true;
|
||||
bool runExitHandlers = false;
|
||||
bool allowVfork = true;
|
||||
|
@ -574,6 +574,12 @@ void commonChildInit(Pipe & logPipe);
|
|||
/* Create a Unix domain socket in listen mode. */
|
||||
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
|
||||
|
||||
/* Bind a Unix domain socket to a path. */
|
||||
void bind(int fd, const std::string & path);
|
||||
|
||||
/* Connect to a Unix domain socket. */
|
||||
void connect(int fd, const std::string & path);
|
||||
|
||||
|
||||
// A Rust/Python-like enumerate() iterator adapter.
|
||||
// Borrowed from http://reedbeta.com/blog/python-like-enumerate-in-cpp17.
|
||||
|
|
|
@ -156,9 +156,6 @@ static void daemonLoop()
|
|||
if (chdir("/") == -1)
|
||||
throw SysError("cannot change current directory");
|
||||
|
||||
// Get rid of children automatically; don't let them become zombies.
|
||||
setSigChldAction(true);
|
||||
|
||||
AutoCloseFD fdSocket;
|
||||
|
||||
// Handle socket-based activation by systemd.
|
||||
|
@ -176,6 +173,9 @@ static void daemonLoop()
|
|||
fdSocket = createUnixDomainSocket(settings.nixDaemonSocketFile, 0666);
|
||||
}
|
||||
|
||||
// Get rid of children automatically; don't let them become zombies.
|
||||
setSigChldAction(true);
|
||||
|
||||
// Loop accepting connections.
|
||||
while (1) {
|
||||
|
||||
|
|
Loading…
Reference in a new issue