summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandolph Tan <randolph@10gen.com>2012-09-18 16:23:32 -0400
committerDan Pasette <dan@10gen.com>2012-09-18 18:33:58 -0400
commit5cc8a693a48f3885df6e77f5ce0f2abf0789d499 (patch)
treee4a636f46eb6ed62057cb71b4328f5e6153bd0a6
parent6be65ade5359a1c9abac96718ccec8e6ed7ae571 (diff)
downloadmongo-5cc8a693a48f3885df6e77f5ce0f2abf0789d499.tar.gz
SERVER-7061 mongos can use invalid ptr to master conn when setShardVersion fails
-rw-r--r--src/mongo/client/dbclient_rs.h6
-rw-r--r--src/mongo/s/shard_version.cpp14
2 files changed, 16 insertions, 4 deletions
diff --git a/src/mongo/client/dbclient_rs.h b/src/mongo/client/dbclient_rs.h
index a74fa7902a3..213ee0dad25 100644
--- a/src/mongo/client/dbclient_rs.h
+++ b/src/mongo/client/dbclient_rs.h
@@ -448,6 +448,12 @@ namespace mongo {
// ---- access raw connections ----
+ /**
+ * WARNING: this method is very dangerous - this object can decide to free the
+ * returned master connection any time.
+ *
+ * @return the reference to the address that points to the master connection.
+ */
DBClientConnection& masterConn();
DBClientConnection& slaveConn();
diff --git a/src/mongo/s/shard_version.cpp b/src/mongo/s/shard_version.cpp
index 7d0ef93da8f..ee959795027 100644
--- a/src/mongo/s/shard_version.cpp
+++ b/src/mongo/s/shard_version.cpp
@@ -232,6 +232,8 @@ namespace mongo {
<< " version: " << version << " manager: " << manager.get()
<< endl;
+ const string versionableServerAddress(conn->getServerAddress());
+
BSONObj result;
if ( setShardVersion( *conn , ns , version , authoritative , result ) ) {
// success!
@@ -246,7 +248,9 @@ namespace mongo {
massert( 10428 , "need_authoritative set but in authoritative mode already" , ! authoritative );
if ( ! authoritative ) {
- checkShardVersion( conn , ns , refManager, 1 , tryNumber + 1 );
+ // use the original connection and get a fresh versionable connection
+ // since conn can be invalidated (or worse, freed) after the failure
+ checkShardVersion(conn_in, ns, refManager, 1, tryNumber + 1);
return true;
}
@@ -268,13 +272,15 @@ namespace mongo {
const int maxNumTries = 7;
if ( tryNumber < maxNumTries ) {
LOG( tryNumber < ( maxNumTries / 2 ) ? 1 : 0 )
- << "going to retry checkShardVersion host: " << conn->getServerAddress() << " " << result << endl;
+ << "going to retry checkShardVersion host: " << versionableServerAddress << " " << result << endl;
sleepmillis( 10 * tryNumber );
- checkShardVersion( conn , ns , refManager, true , tryNumber + 1 );
+ // use the original connection and get a fresh versionable connection
+ // since conn can be invalidated (or worse, freed) after the failure
+ checkShardVersion(conn_in, ns, refManager, true, tryNumber + 1);
return true;
}
- string errmsg = str::stream() << "setShardVersion failed host: " << conn->getServerAddress() << " " << result;
+ string errmsg = str::stream() << "setShardVersion failed host: " << versionableServerAddress << " " << result;
log() << " " << errmsg << endl;
massert( 10429 , errmsg , 0 );
return true;