aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libutil/error.cc5
-rw-r--r--src/libutil/error.hh4
-rw-r--r--src/libutil/util.cc17
3 files changed, 26 insertions, 0 deletions
diff --git a/src/libutil/error.cc b/src/libutil/error.cc
index c9d61942a..4a1b346ef 100644
--- a/src/libutil/error.cc
+++ b/src/libutil/error.cc
@@ -14,6 +14,11 @@ void BaseError::addTrace(std::shared_ptr<AbstractPos> && e, hintformat hint, boo
err.traces.push_front(Trace { .pos = std::move(e), .hint = hint, .frame = frame });
}
+void throwExceptionSelfCheck(){
+ // This is meant to be caught in initLibUtil()
+ throw SysError("C++ exception handling is broken. This would appear to be a problem with the way Nix was compiled and/or linked and/or loaded.");
+}
+
// c++ std::exception descendants must have a 'const char* what()' function.
// This stringifies the error and caches it for use by what(), or similarly by msg().
const std::string & BaseError::calcWhat() const
diff --git a/src/libutil/error.hh b/src/libutil/error.hh
index 6a0923081..be5c5e252 100644
--- a/src/libutil/error.hh
+++ b/src/libutil/error.hh
@@ -214,4 +214,8 @@ public:
}
};
+/** Throw an exception for the purpose of checking that exception handling works; see 'initLibUtil()'.
+ */
+void throwExceptionSelfCheck();
+
}
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 26f9dc8a8..f24a6e165 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -48,6 +48,23 @@ extern char * * environ __attribute__((weak));
namespace nix {
void initLibUtil() {
+ // Check that exception handling works. Exception handling has been observed
+ // not to work on darwin when the linker flags aren't quite right.
+ // In this case we don't want to expose the user to some unrelated uncaught
+ // exception, but rather tell them exactly that exception handling is
+ // broken.
+ // When exception handling fails, the message tends to be printed by the
+ // C++ runtime, followed by an abort.
+ // For example on macOS we might see an error such as
+ // libc++abi: terminating with uncaught exception of type nix::SysError: error: C++ exception handling is broken. This would appear to be a problem with the way Nix was compiled and/or linked and/or loaded.
+ bool caught = false;
+ try {
+ throwExceptionSelfCheck();
+ } catch (nix::Error _e) {
+ caught = true;
+ }
+ // This is not actually the main point of this check, but let's make sure anyway:
+ assert(caught);
}
std::optional<std::string> getEnv(const std::string & key)