diff options
author | Mathias Stearn <mathias@10gen.com> | 2014-01-30 15:57:28 -0500 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2014-01-30 17:13:54 -0500 |
commit | e472493129c095170f1322a98af67bdf5208fe51 (patch) | |
tree | 9a930fd260ed25d7f74ae94718d3d64bcec3125e | |
parent | adf15ca89abe4027391582a213d649b0f5be62a8 (diff) | |
download | mongo-e472493129c095170f1322a98af67bdf5208fe51.tar.gz |
SERVER-5724 Mark dbtemprelase{,cond,if} destructors as throwing
This is a stop-gap solution to prevent c++11 builds from terminating when
relocking and reinitializing Client::Context fails. In c++11 destructors that
aren't explicitly marked as throwing are implicitly noexcept(true).
For similar reasons it is invalid to put dbtemprelease into a smart pointer
since the smart pointer's destructor isn't marked as throwing. The few places
that did that were also changed.
dbtemprelasewritelock is unused so it was removed rather than fixed.
-rw-r--r-- | src/mongo/db/cloner.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/commands/mr.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/db.h | 42 | ||||
-rw-r--r-- | src/mongo/db/dbcommands.cpp | 10 |
4 files changed, 28 insertions, 40 deletions
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp index cff2d818d7d..acc74af6125 100644 --- a/src/mongo/db/cloner.cpp +++ b/src/mongo/db/cloner.cpp @@ -59,10 +59,16 @@ namespace mongo { /** Selectively release the mutex based on a parameter. */ class dbtempreleaseif { + MONGO_DISALLOW_COPYING(dbtempreleaseif); public: dbtempreleaseif( bool release ) : _impl( release ? new dbtemprelease() : 0 ) {} + ~dbtempreleaseif() throw(DBException) { + if (_impl) + delete _impl; + } private: - shared_ptr< dbtemprelease > _impl; + // can't use a smart pointer because we need throw annotation on destructor + dbtemprelease* _impl; }; void mayInterrupt( bool mayBeInterrupted ) { diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp index eebc3fb3330..535f5ef9bb0 100644 --- a/src/mongo/db/commands/mr.cpp +++ b/src/mongo/db/commands/mr.cpp @@ -977,22 +977,24 @@ namespace mongo { } runner->saveState(); - auto_ptr<dbtempreleasecond> yield(new dbtempreleasecond()); + + // can't be a smart pointer since it needs throw annotation on destructor + dbtempreleasecond* yield = new dbtempreleasecond(); try { // reduce a finalize array finalReduce( all ); } catch (...) { - yield.reset(); + delete yield; // if throws, replaces current exception rather than terminating. throw; } + delete yield; all.clear(); prev = o; all.push_back( o ); - yield.reset(); if (!runner->restoreState()) { break; } diff --git a/src/mongo/db/db.h b/src/mongo/db/db.h index c178dedd323..9ff1a1541a7 100644 --- a/src/mongo/db/db.h +++ b/src/mongo/db/db.h @@ -41,6 +41,12 @@ namespace mongo { // todo: relocked is being called when there was no unlock below. // that is weird. + /** + * Releases the current lock for the duration of its lifetime. + * + * WARNING: do not put in a smart pointer or any other class. If you absolutely must, you need + * to add the throw(DBException) annotation to it's destructor. + */ struct dbtemprelease { Client::Context * _context; scoped_ptr<Lock::TempRelease> tr; @@ -58,34 +64,7 @@ namespace mongo { verify( c.curop() ); c.curop()->yielded(); } - ~dbtemprelease() { - tr.reset(); - if ( _context ) - _context->relocked(); - } - }; - - /** must be write locked - no verify(and no release) if nested write lock - a lot like dbtempreleasecond, eliminate? - */ - struct dbtempreleasewritelock { - Client::Context * _context; - int _locktype; - scoped_ptr<Lock::TempRelease> tr; - dbtempreleasewritelock() { - const Client& c = cc(); - _context = c.getContext(); - verify( Lock::isW() ); - if( Lock::nested() ) - return; - if ( _context ) - _context->unlocked(); - tr.reset(new Lock::TempRelease); - verify( c.curop() ); - c.curop()->yielded(); - } - ~dbtempreleasewritelock() { + ~dbtemprelease() throw(DBException) { tr.reset(); if ( _context ) _context->relocked(); @@ -93,7 +72,10 @@ namespace mongo { }; /** - only does a temp release if we're not nested and have a lock + * only does a temp release if we're not nested and have a lock + * + * WARNING: do not put in a smart pointer or any other class. If you absolutely must, you need + * to add the throw(DBException) annotation to it's destructor. */ class dbtempreleasecond : boost::noncopyable { dbtemprelease * real; @@ -107,7 +89,7 @@ namespace mongo { } } } - ~dbtempreleasecond() { + ~dbtempreleasecond() throw(DBException) { if ( real ) { delete real; real = 0; diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp index 9c4f04753f1..cb126cf408f 100644 --- a/src/mongo/db/dbcommands.cpp +++ b/src/mongo/db/dbcommands.cpp @@ -784,14 +784,12 @@ namespace mongo { // Save state, yield, run the MD5, and reacquire lock. runner->saveState(); - // auto_ptr<dbtempreleasecond> yield(new dbtempreleasecond()); - scoped_ptr<dbtempreleasecond> yield(new dbtempreleasecond()); - - md5_append( &st , (const md5_byte_t*)(data) , len ); - n++; try { - yield.reset(); + dbtempreleasecond yield; + + md5_append( &st , (const md5_byte_t*)(data) , len ); + n++; } catch (SendStaleConfigException&) { log() << "metadata changed during filemd5" << endl; |