summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2014-01-30 15:57:28 -0500
committerMathias Stearn <mathias@10gen.com>2014-01-30 17:13:54 -0500
commite472493129c095170f1322a98af67bdf5208fe51 (patch)
tree9a930fd260ed25d7f74ae94718d3d64bcec3125e
parentadf15ca89abe4027391582a213d649b0f5be62a8 (diff)
downloadmongo-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.cpp8
-rw-r--r--src/mongo/db/commands/mr.cpp8
-rw-r--r--src/mongo/db/db.h42
-rw-r--r--src/mongo/db/dbcommands.cpp10
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;