mirror of
https://github.com/NixOS/nix
synced 2025-07-08 06:53:54 +02:00
PathSubstitutionGoal: Clean up pipe
If there were many top-level goals (which are not destroyed until the
very end), commands like
$ nix copy --to 'ssh://localhost?remote-store=/tmp/nix' \
/run/current-system --no-check-sigs --substitute-on-destination
could fail with "Too many open files". So now we do some explicit
cleanup from amDone(). It would be cleaner to separate goals from
their temporary internal state, but that would be a bigger refactor.
Backport 8a29052cb2
This commit is contained in:
parent
8223cc5663
commit
c31ce3dffe
3 changed files with 36 additions and 14 deletions
|
@ -179,6 +179,8 @@ public:
|
||||||
|
|
||||||
virtual string key() = 0;
|
virtual string key() = 0;
|
||||||
|
|
||||||
|
virtual void cleanup() { }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void amDone(ExitCode result);
|
virtual void amDone(ExitCode result);
|
||||||
|
@ -424,6 +426,8 @@ void Goal::amDone(ExitCode result)
|
||||||
}
|
}
|
||||||
waiters.clear();
|
waiters.clear();
|
||||||
worker.removeGoal(shared_from_this());
|
worker.removeGoal(shared_from_this());
|
||||||
|
|
||||||
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3895,6 +3899,8 @@ public:
|
||||||
void handleChildOutput(int fd, const string & data) override;
|
void handleChildOutput(int fd, const string & data) override;
|
||||||
void handleEOF(int fd) override;
|
void handleEOF(int fd) override;
|
||||||
|
|
||||||
|
void cleanup() override;
|
||||||
|
|
||||||
Path getStorePath() { return storePath; }
|
Path getStorePath() { return storePath; }
|
||||||
|
|
||||||
void amDone(ExitCode result) override
|
void amDone(ExitCode result) override
|
||||||
|
@ -3918,15 +3924,7 @@ SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, Repa
|
||||||
|
|
||||||
SubstitutionGoal::~SubstitutionGoal()
|
SubstitutionGoal::~SubstitutionGoal()
|
||||||
{
|
{
|
||||||
try {
|
cleanup();
|
||||||
if (thr.joinable()) {
|
|
||||||
// FIXME: signal worker thread to quit.
|
|
||||||
thr.join();
|
|
||||||
worker.childTerminated(this);
|
|
||||||
}
|
|
||||||
} catch (...) {
|
|
||||||
ignoreException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3961,6 +3959,8 @@ void SubstitutionGoal::tryNext()
|
||||||
{
|
{
|
||||||
trace("trying next substituter");
|
trace("trying next substituter");
|
||||||
|
|
||||||
|
cleanup();
|
||||||
|
|
||||||
if (subs.size() == 0) {
|
if (subs.size() == 0) {
|
||||||
/* None left. Terminate this goal and let someone else deal
|
/* None left. Terminate this goal and let someone else deal
|
||||||
with it. */
|
with it. */
|
||||||
|
@ -4088,7 +4088,7 @@ void SubstitutionGoal::tryToRun()
|
||||||
thr = std::thread([this]() {
|
thr = std::thread([this]() {
|
||||||
try {
|
try {
|
||||||
/* Wake up the worker loop when we're done. */
|
/* Wake up the worker loop when we're done. */
|
||||||
Finally updateStats([this]() { outPipe.writeSide = -1; });
|
Finally updateStats([this]() { outPipe.writeSide.close(); });
|
||||||
|
|
||||||
Activity act(*logger, actSubstitute, Logger::Fields{storePath, sub->getUri()});
|
Activity act(*logger, actSubstitute, Logger::Fields{storePath, sub->getUri()});
|
||||||
PushActivity pact(act.id);
|
PushActivity pact(act.id);
|
||||||
|
@ -4172,6 +4172,20 @@ void SubstitutionGoal::handleEOF(int fd)
|
||||||
if (fd == outPipe.readSide.get()) worker.wakeUp(shared_from_this());
|
if (fd == outPipe.readSide.get()) worker.wakeUp(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SubstitutionGoal::cleanup()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (thr.joinable()) {
|
||||||
|
// FIXME: signal worker thread to quit.
|
||||||
|
thr.join();
|
||||||
|
worker.childTerminated(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
outPipe.close();
|
||||||
|
} catch (...) {
|
||||||
|
ignoreException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -753,6 +753,7 @@ void AutoCloseFD::close()
|
||||||
if (::close(fd) == -1)
|
if (::close(fd) == -1)
|
||||||
/* This should never happen. */
|
/* This should never happen. */
|
||||||
throw SysError(format("closing file descriptor %1%") % fd);
|
throw SysError(format("closing file descriptor %1%") % fd);
|
||||||
|
fd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,6 +771,12 @@ int AutoCloseFD::release()
|
||||||
return oldFD;
|
return oldFD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Pipe::close()
|
||||||
|
{
|
||||||
|
readSide.close();
|
||||||
|
writeSide.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Pipe::create()
|
void Pipe::create()
|
||||||
{
|
{
|
||||||
|
@ -1080,7 +1087,7 @@ void runProgram2(const RunOptions & options)
|
||||||
throw SysError("executing '%1%'", options.program);
|
throw SysError("executing '%1%'", options.program);
|
||||||
}, processOptions);
|
}, processOptions);
|
||||||
|
|
||||||
out.writeSide = -1;
|
out.writeSide.close();
|
||||||
|
|
||||||
std::thread writerThread;
|
std::thread writerThread;
|
||||||
|
|
||||||
|
@ -1093,7 +1100,7 @@ void runProgram2(const RunOptions & options)
|
||||||
|
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
in.readSide = -1;
|
in.readSide.close();
|
||||||
writerThread = std::thread([&]() {
|
writerThread = std::thread([&]() {
|
||||||
try {
|
try {
|
||||||
std::vector<unsigned char> buf(8 * 1024);
|
std::vector<unsigned char> buf(8 * 1024);
|
||||||
|
@ -1110,7 +1117,7 @@ void runProgram2(const RunOptions & options)
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
promise.set_exception(std::current_exception());
|
promise.set_exception(std::current_exception());
|
||||||
}
|
}
|
||||||
in.writeSide = -1;
|
in.writeSide.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,6 @@ public:
|
||||||
class AutoCloseFD
|
class AutoCloseFD
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
void close();
|
|
||||||
public:
|
public:
|
||||||
AutoCloseFD();
|
AutoCloseFD();
|
||||||
AutoCloseFD(int fd);
|
AutoCloseFD(int fd);
|
||||||
|
@ -202,6 +201,7 @@ public:
|
||||||
int get() const;
|
int get() const;
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
int release();
|
int release();
|
||||||
|
void close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,6 +210,7 @@ class Pipe
|
||||||
public:
|
public:
|
||||||
AutoCloseFD readSide, writeSide;
|
AutoCloseFD readSide, writeSide;
|
||||||
void create();
|
void create();
|
||||||
|
void close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue