diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2017-03-03T18·28+0100 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2017-03-03T18·28+0100 |
commit | 8490ee37a6dbfb66e1b3dbaf88918bea044b143a (patch) | |
tree | f0a244e19a8b7412e93b1f487aa4c8d572ff19e4 | |
parent | d3eb1cf3bbf57a33ac2e71a19a150c077011ecd9 (diff) |
SSHMaster: Make thread-safe
-rw-r--r-- | src/libstore/ssh.cc | 22 | ||||
-rw-r--r-- | src/libstore/ssh.hh | 24 |
2 files changed, 29 insertions, 17 deletions
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::Connection> SSHMaster::startCommand(const std::string & command) { - startMaster(); + Path socketPath = startMaster(); Pipe in, out; in.create(); @@ -27,7 +27,7 @@ std::unique_ptr<SSHMaster::Connection> 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::Connection> 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<AutoDelete>(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<AutoDelete>(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<AutoDelete> tmpDir; - Path socketPath; + const std::string host; + const std::string keyFile; + const bool useMaster; + const bool compress; + + struct State + { + Pid sshMaster; + std::unique_ptr<AutoDelete> tmpDir; + Path socketPath; + }; + + Sync<State> state_; public: @@ -34,8 +41,7 @@ public: std::unique_ptr<Connection> startCommand(const std::string & command); - void startMaster(); - + Path startMaster(); }; } |