Split ignoreException to avoid suppressing CTRL-C

This splits `ignoreException` into `ignoreExceptionExceptInterrupt`
(which ignores all exceptions except `Interrupt`, which indicates a
SIGINT/CTRL-C) and `ignoreExceptionInDestructor` (which ignores all
exceptions, so that destructors do not throw exceptions).

This prevents many cases where Nix ignores CTRL-C entirely.
See: https://github.com/NixOS/nix/issues/7245

Upstream-PR: https://github.com/NixOS/nix/pull/11618
Change-Id: Ie7d2467eedbe840d1b9fa2e88a4e88e4ab26a87b
This commit is contained in:
Robert Hensing
2024-10-01 15:49:56 -07:00
committed by Rebecca Turner
parent 7752927660
commit ee0c195eba
28 changed files with 76 additions and 43 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ unsigned int getMaxCPU()
auto period = cpuMaxParts[1];
if (quota != "max")
return std::ceil(std::stoi(quota) / std::stof(period));
} catch (Error &) { ignoreException(lvlDebug); }
} catch (Error &) { ignoreExceptionInDestructor(lvlDebug); }
#endif
return 0;
+13 -1
View File
@@ -4,6 +4,7 @@
#include "position.hh"
#include "terminal.hh"
#include "strings.hh"
#include "signals.hh"
#include <iostream>
#include <optional>
@@ -416,7 +417,7 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
return out;
}
void ignoreException(Verbosity lvl)
void ignoreExceptionInDestructor(Verbosity lvl)
{
/* Make sure no exceptions leave this function.
printError() also throws when remote is closed. */
@@ -429,4 +430,15 @@ void ignoreException(Verbosity lvl)
} catch (...) { }
}
void ignoreExceptionExceptInterrupt(Verbosity lvl)
{
try {
throw;
} catch (const Interrupted & e) {
throw;
} catch (std::exception & e) {
printMsg(lvl, "error (ignored): %1%", e.what());
}
}
}
+16 -1
View File
@@ -204,7 +204,22 @@ public:
/**
* Exception handling in destructors: print an error message, then
* ignore the exception.
*
* If you're not in a destructor, you usually want to use `ignoreExceptionExceptInterrupt()`.
*
* This function might also be used in callbacks whose caller may not handle exceptions,
* but ideally we propagate the exception using an exception_ptr in such cases.
* See e.g. `PackBuilderContext`
*/
void ignoreException(Verbosity lvl = lvlError);
void ignoreExceptionInDestructor(Verbosity lvl = lvlError);
/**
* Not destructor-safe.
* Print an error message, then ignore the exception.
* If the exception is an `Interrupted` exception, rethrow it.
*
* This may be used in a few places where Interrupt can't happen, but that's ok.
*/
void ignoreExceptionExceptInterrupt(Verbosity lvl = lvlError);
}
+1 -1
View File
@@ -146,7 +146,7 @@ AutoCloseFD::~AutoCloseFD()
try {
close();
} catch (...) {
ignoreException();
ignoreExceptionInDestructor();
}
}
+1 -1
View File
@@ -522,7 +522,7 @@ AutoDelete::~AutoDelete()
}
}
} catch (...) {
ignoreException();
ignoreExceptionInDestructor();
}
}
+1 -1
View File
@@ -352,7 +352,7 @@ Activity::~Activity()
try {
logger.stopActivity(id);
} catch (...) {
ignoreException();
ignoreExceptionInDestructor();
}
}
+1 -1
View File
@@ -83,7 +83,7 @@ void BufferedSink::flush()
FdSink::~FdSink()
{
try { flush(); } catch (...) { ignoreException(); }
try { flush(); } catch (...) { ignoreExceptionInDestructor(); }
}
+2 -2
View File
@@ -549,7 +549,7 @@ struct FramedSource : Source
}
}
} catch (...) {
ignoreException();
ignoreExceptionInDestructor();
}
}
@@ -595,7 +595,7 @@ struct FramedSink : nix::BufferedSink
to << 0;
to.flush();
} catch (...) {
ignoreException();
ignoreExceptionInDestructor();
}
}
+1 -1
View File
@@ -78,7 +78,7 @@ void triggerInterrupt()
try {
callback();
} catch (...) {
ignoreException();
ignoreExceptionInDestructor();
}
}
}
+2 -3
View File
@@ -109,9 +109,8 @@ void ThreadPool::doWork(bool mainThread)
try {
std::rethrow_exception(exc);
} catch (std::exception & e) {
if (!dynamic_cast<Interrupted*>(&e) &&
!dynamic_cast<ThreadPoolShutDown*>(&e))
ignoreException();
if (!dynamic_cast<ThreadPoolShutDown*>(&e))
ignoreExceptionExceptInterrupt();
} catch (...) {
}
}