about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2007-05-01T15·16+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2007-05-01T15·16+0000
commitcbfac2fdccc83b04d9c2027e9e21070d4ac7c7e5 (patch)
tree9bff2f93fb123a3ad05bb3712e3d2a875c6da53b /src
parent644946feed146396c00c288337bad26428970aa4 (diff)
* Set a terminate() handler to ensure that we leave the BDB
  environment cleanly even when an exception is thrown from a
  destructor.  We still crash, but we don't take all other Nix
  processes with us.

Diffstat (limited to 'src')
-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 568c975c2978..ebdbeb11e114 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 7009876f1bcd..5c8b31cf6a6b 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 7b7efc84b3d1..cd8bc1a3394f 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 1aab90d38c52..449a4c448f0f 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 ae5af249203e..d61b35bdfbe0 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 4d284ccfdc68..63389867fed8 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();
+
+
 }