* 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.
This commit is contained in:
		
							parent
							
								
									644946feed
								
							
						
					
					
						commit
						cbfac2fdcc
					
				
					 6 changed files with 55 additions and 8 deletions
				
			
		|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <cctype> | #include <cctype> | ||||||
|  | #include <exception> | ||||||
| 
 | 
 | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  | @ -81,6 +82,23 @@ struct RemoveTempRoots | ||||||
| void initDerivationsHelpers(); | 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
 | /* Initialize and reorder arguments, then call the actual argument
 | ||||||
|    processor. */ |    processor. */ | ||||||
| static void initAndRun(int argc, char * * argv) | static void initAndRun(int argc, char * * argv) | ||||||
|  | @ -195,6 +213,12 @@ static void initAndRun(int argc, char * * argv) | ||||||
|        exit. */ |        exit. */ | ||||||
|     RemoveTempRoots removeTempRoots; /* unused variable - don't remove */ |     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); |     run(remaining); | ||||||
| 
 | 
 | ||||||
|     /* Close the Nix database. */ |     /* Close the Nix database. */ | ||||||
|  |  | ||||||
|  | @ -685,8 +685,8 @@ DerivationGoal::~DerivationGoal() | ||||||
|     try { |     try { | ||||||
|         killChild(); |         killChild(); | ||||||
|         deleteTmpDir(false); |         deleteTmpDir(false); | ||||||
|     } catch (Error & e) { |     } catch (...) { | ||||||
|         printMsg(lvlError, format("error (ignored): %1%") % e.msg()); |         ignoreException(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -161,7 +161,11 @@ LocalStore::LocalStore(bool reserveSpace) | ||||||
| LocalStore::~LocalStore() | LocalStore::~LocalStore() | ||||||
| { | { | ||||||
|     /* If the database isn't open, this is a NOP. */ |     /* If the database isn't open, this is a NOP. */ | ||||||
|     nixDB.close(); |     try { | ||||||
|  |         nixDB.close(); | ||||||
|  |     } catch (...) { | ||||||
|  |         ignoreException(); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -148,8 +148,8 @@ RemoteStore::~RemoteStore() | ||||||
|         fdSocket.close(); |         fdSocket.close(); | ||||||
|         if (child != -1) |         if (child != -1) | ||||||
|             child.wait(true); |             child.wait(true); | ||||||
|     } catch (Error & e) { |     } catch (...) { | ||||||
|         printMsg(lvlError, format("error (ignored): %1%") % e.msg()); |         ignoreException(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -444,7 +444,11 @@ void warnOnce(bool & haveWarned, const format & f) | ||||||
| 
 | 
 | ||||||
| static void defaultWriteToStderr(const unsigned char * buf, size_t count) | 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 { |     try { | ||||||
|         close(); |         close(); | ||||||
|     } catch (Error & e) { |     } catch (...) { | ||||||
|         printMsg(lvlError, format("error (ignored): %1%") % e.msg()); |         ignoreException(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -968,5 +972,15 @@ bool string2Int(const string & s, int & n) | ||||||
|     return str && str.get() == EOF; |     return str && str.get() == EOF; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | void ignoreException() | ||||||
|  | { | ||||||
|  |     try { | ||||||
|  |         throw; | ||||||
|  |     } catch (std::exception & e) { | ||||||
|  |         printMsg(lvlError, format("error (ignored): %1%") % e.what()); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|   |   | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -280,6 +280,11 @@ string int2String(int n); | ||||||
| bool string2Int(const string & s, int & n); | bool string2Int(const string & s, int & n); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /* Exception handling in destructors: print an error message, then
 | ||||||
|  |    ignore the exception. */ | ||||||
|  | void ignoreException(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue