From 8490ee37a6dbfb66e1b3dbaf88918bea044b143a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 3 Mar 2017 19:28:27 +0100 Subject: SSHMaster: Make thread-safe --- src/libstore/ssh.cc | 22 ++++++++++++++-------- src/libstore/ssh.hh | 24 +++++++++++++++--------- 2 files changed, 29 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc index 7c3de4a48271..4f88fa64dbd1 100644 --- a/src/libstore/ssh.cc +++ b/src/libstore/ssh.cc @@ -4,7 +4,7 @@ namespace nix { std::unique_ptr SSHMaster::startCommand(const std::string & command) { - startMaster(); + Path socketPath = startMaster(); Pipe in, out; in.create(); @@ -27,7 +27,7 @@ std::unique_ptr SSHMaster::startCommand(const std::string args.insert(args.end(), {"-i", keyFile}); if (compress) args.push_back("-C"); - if (useMaster) + if (socketPath != "") args.insert(args.end(), {"-S", socketPath}); args.push_back(command); execvp(args.begin()->c_str(), stringsToCharPtrs(args).data()); @@ -45,18 +45,22 @@ std::unique_ptr SSHMaster::startCommand(const std::string return conn; } -void SSHMaster::startMaster() +Path SSHMaster::startMaster() { - if (!useMaster || sshMaster != -1) return; + if (!useMaster) return ""; - tmpDir = std::make_unique(createTempDir("", "nix", true, true, 0700)); + auto state(state_.lock()); - socketPath = (Path) *tmpDir + "/ssh.sock"; + if (state->sshMaster != -1) return state->socketPath; + + state->tmpDir = std::make_unique(createTempDir("", "nix", true, true, 0700)); + + state->socketPath = (Path) *state->tmpDir + "/ssh.sock"; Pipe out; out.create(); - sshMaster = startProcess([&]() { + state->sshMaster = startProcess([&]() { restoreSignals(); close(out.readSide.get()); @@ -65,7 +69,7 @@ void SSHMaster::startMaster() throw SysError("duping over stdout"); Strings args = - { "ssh", host.c_str(), "-M", "-N", "-S", socketPath + { "ssh", host.c_str(), "-M", "-N", "-S", state->socketPath , "-o", "LocalCommand=echo started" , "-o", "PermitLocalCommand=yes" }; @@ -88,6 +92,8 @@ void SSHMaster::startMaster() if (reply != "started") throw Error("failed to start SSH master connection to ā€˜%sā€™", host); + + return state->socketPath; } } diff --git a/src/libstore/ssh.hh b/src/libstore/ssh.hh index 2d2b98370396..72238dad79ab 100644 --- a/src/libstore/ssh.hh +++ b/src/libstore/ssh.hh @@ -1,6 +1,7 @@ #pragma once #include "util.hh" +#include "sync.hh" namespace nix { @@ -8,13 +9,19 @@ class SSHMaster { private: - std::string host; - std::string keyFile; - bool useMaster; - bool compress; - Pid sshMaster; - std::unique_ptr tmpDir; - Path socketPath; + const std::string host; + const std::string keyFile; + const bool useMaster; + const bool compress; + + struct State + { + Pid sshMaster; + std::unique_ptr tmpDir; + Path socketPath; + }; + + Sync state_; public: @@ -34,8 +41,7 @@ public: std::unique_ptr startCommand(const std::string & command); - void startMaster(); - + Path startMaster(); }; } -- cgit 1.4.1