aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libmain/shared.cc24
-rw-r--r--src/libstore/build.cc4
-rw-r--r--src/libstore/local-store.cc6
-rw-r--r--src/libstore/remote-store.cc4
-rw-r--r--src/libutil/util.cc20
-rw-r--r--src/libutil/util.hh5
6 files changed, 55 insertions, 8 deletions
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index 568c975c2..ebdbeb11e 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -7,6 +7,7 @@
#include <iostream>
#include <cctype>
+#include <exception>
#include <sys/stat.h>
#include <unistd.h>
@@ -81,6 +82,23 @@ struct RemoveTempRoots
void initDerivationsHelpers();
+static void closeStore()
+{
+ try {
+ throw;
+ } catch (std::exception & e) {
+ printMsg(lvlError,
+ format("FATAL: unexpected exception (closing store and aborting): %1%") % e.what());
+ }
+ try {
+ store.reset((StoreAPI *) 0);
+ } catch (...) {
+ ignoreException();
+ }
+ abort();
+}
+
+
/* Initialize and reorder arguments, then call the actual argument
processor. */
static void initAndRun(int argc, char * * argv)
@@ -195,6 +213,12 @@ static void initAndRun(int argc, char * * argv)
exit. */
RemoveTempRoots removeTempRoots; /* unused variable - don't remove */
+ /* Make sure that the database gets closed properly, even if
+ terminate() is called (which happens sometimes due to bugs in
+ destructor/exceptions interaction, but that needn't preclude a
+ clean shutdown of the database). */
+ std::set_terminate(closeStore);
+
run(remaining);
/* Close the Nix database. */
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 7009876f1..5c8b31cf6 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -685,8 +685,8 @@ DerivationGoal::~DerivationGoal()
try {
killChild();
deleteTmpDir(false);
- } catch (Error & e) {
- printMsg(lvlError, format("error (ignored): %1%") % e.msg());
+ } catch (...) {
+ ignoreException();
}
}
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 7b7efc84b..cd8bc1a33 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -161,7 +161,11 @@ LocalStore::LocalStore(bool reserveSpace)
LocalStore::~LocalStore()
{
/* If the database isn't open, this is a NOP. */
- nixDB.close();
+ try {
+ nixDB.close();
+ } catch (...) {
+ ignoreException();
+ }
}
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 1aab90d38..449a4c448 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -148,8 +148,8 @@ RemoteStore::~RemoteStore()
fdSocket.close();
if (child != -1)
child.wait(true);
- } catch (Error & e) {
- printMsg(lvlError, format("error (ignored): %1%") % e.msg());
+ } catch (...) {
+ ignoreException();
}
}
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index ae5af2492..d61b35bdf 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -444,7 +444,11 @@ void warnOnce(bool & haveWarned, const format & f)
static void defaultWriteToStderr(const unsigned char * buf, size_t count)
{
- writeFull(STDERR_FILENO, buf, count);
+ try {
+ writeFull(STDERR_FILENO, buf, count);
+ } catch (SysError & e) {
+ /* ignore EPIPE etc. */
+ }
}
@@ -545,8 +549,8 @@ AutoCloseFD::~AutoCloseFD()
{
try {
close();
- } catch (Error & e) {
- printMsg(lvlError, format("error (ignored): %1%") % e.msg());
+ } catch (...) {
+ ignoreException();
}
}
@@ -968,5 +972,15 @@ bool string2Int(const string & s, int & n)
return str && str.get() == EOF;
}
+
+void ignoreException()
+{
+ try {
+ throw;
+ } catch (std::exception & e) {
+ printMsg(lvlError, format("error (ignored): %1%") % e.what());
+ }
+}
+
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 4d284ccfd..63389867f 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -280,6 +280,11 @@ string int2String(int n);
bool string2Int(const string & s, int & n);
+/* Exception handling in destructors: print an error message, then
+ ignore the exception. */
+void ignoreException();
+
+
}