Fix deadlock in SSHMaster::addCommonSSHOpts()
When useMaster is true, startMaster() acquires the state lock, then calls isMasterRunning(), which calls addCommonSSHOpts(), which tries to acquire the state lock again, causing a deadlock. The solution is to move tmpDir out of the state. It doesn't need to be there in the first place because it never changes.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "nix/util/ref.hh"
|
||||
#include "nix/util/sync.hh"
|
||||
#include "nix/util/url.hh"
|
||||
#include "nix/util/processes.hh"
|
||||
@@ -26,12 +27,13 @@ private:
|
||||
const bool compress;
|
||||
const Descriptor logFD;
|
||||
|
||||
ref<AutoDelete> tmpDir;
|
||||
|
||||
struct State
|
||||
{
|
||||
#ifndef _WIN32 // TODO re-enable on Windows, once we can start processes.
|
||||
Pid sshMaster;
|
||||
#endif
|
||||
std::unique_ptr<AutoDelete> tmpDir;
|
||||
Path socketPath;
|
||||
};
|
||||
|
||||
|
||||
@@ -84,23 +84,20 @@ SSHMaster::SSHMaster(
|
||||
, useMaster(useMaster && !fakeSSH)
|
||||
, compress(compress)
|
||||
, logFD(logFD)
|
||||
, tmpDir(make_ref<AutoDelete>(createTempDir("", "nix", 0700)))
|
||||
{
|
||||
checkValidAuthority(authority);
|
||||
auto state(state_.lock());
|
||||
state->tmpDir = std::make_unique<AutoDelete>(createTempDir("", "nix", 0700));
|
||||
}
|
||||
|
||||
void SSHMaster::addCommonSSHOpts(Strings & args)
|
||||
{
|
||||
auto state(state_.lock());
|
||||
|
||||
auto sshArgs = getNixSshOpts();
|
||||
args.insert(args.end(), sshArgs.begin(), sshArgs.end());
|
||||
|
||||
if (!keyFile.empty())
|
||||
args.insert(args.end(), {"-i", keyFile});
|
||||
if (!sshPublicHostKey.empty()) {
|
||||
std::filesystem::path fileName = state->tmpDir->path() / "host-key";
|
||||
std::filesystem::path fileName = tmpDir->path() / "host-key";
|
||||
writeFile(fileName.string(), authority.host + " " + sshPublicHostKey + "\n");
|
||||
args.insert(args.end(), {"-oUserKnownHostsFile=" + fileName.string()});
|
||||
}
|
||||
@@ -241,7 +238,7 @@ Path SSHMaster::startMaster()
|
||||
if (state->sshMaster != INVALID_DESCRIPTOR)
|
||||
return state->socketPath;
|
||||
|
||||
state->socketPath = (Path) *state->tmpDir + "/ssh.sock";
|
||||
state->socketPath = (Path) *tmpDir + "/ssh.sock";
|
||||
|
||||
Pipe out;
|
||||
out.create();
|
||||
|
||||
Reference in New Issue
Block a user