0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-28 07:59:02 +01:00

SERVER-17282 fix use after free in the case of a database drop during a yield

This commit is contained in:
David Storch 2015-03-18 15:24:09 -04:00
parent b91ea55090
commit eac8d16add
3 changed files with 19 additions and 11 deletions

View File

@ -43,6 +43,7 @@
#include "mongo/db/query/explain.h"
#include "mongo/db/query/find.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/db/server_parameters.h"
#include "mongo/db/stats/counters.h"
#include "mongo/s/d_state.h"
#include "mongo/util/log.h"
@ -220,6 +221,9 @@ namespace mongo {
AutoGetCollectionForRead ctx(txn, nss);
Collection* collection = ctx.getCollection();
const int dbProfilingLevel = ctx.getDb() ? ctx.getDb()->getProfilingLevel() :
serverGlobalParams.defaultProfile;
// 3) Get the execution plan for the query.
//
// TODO: Do we need to handle oplog replay here?
@ -251,7 +255,8 @@ namespace mongo {
// there is no ClientCursor id, and then return.
const int numResults = 0;
const CursorId cursorId = 0;
endQueryOp(ctx, execHolder.get(), numResults, cursorId, txn->getCurOp());
endQueryOp(execHolder.get(), dbProfilingLevel, numResults, cursorId,
txn->getCurOp());
Command::appendCursorResponseObject(cursorId, nss.ns(), BSONArray(), &result);
return true;
}
@ -333,7 +338,7 @@ namespace mongo {
}
// Fill out curop based on the results.
endQueryOp(ctx, exec, numResults, cursorId, txn->getCurOp());
endQueryOp(exec, dbProfilingLevel, numResults, cursorId, txn->getCurOp());
// 7) Generate the response object to send to the client.
Command::appendCursorResponseObject(cursorId, nss.ns(), firstBatch.arr(), &result);

View File

@ -166,8 +166,8 @@ namespace mongo {
curop->setQuery(queryObj);
}
void endQueryOp(const AutoGetCollectionForRead& ctx,
PlanExecutor* exec,
void endQueryOp(PlanExecutor* exec,
int dbProfilingLevel,
int numResults,
CursorId cursorId,
CurOp* curop) {
@ -186,8 +186,6 @@ namespace mongo {
curop->debug().nscannedObjects = summaryStats.totalDocsExamined;
curop->debug().idhack = summaryStats.isIdhack;
const int dbProfilingLevel = (ctx.getDb() != NULL) ? ctx.getDb()->getProfilingLevel() :
serverGlobalParams.defaultProfile;
const logger::LogComponent queryLogComponent = logger::LogComponent::kQuery;
const logger::LogSeverity logLevelOne = logger::LogSeverity::Debug(1);
@ -733,6 +731,9 @@ namespace mongo {
AutoGetCollectionForRead ctx(txn, nss);
Collection* collection = ctx.getCollection();
const int dbProfilingLevel = ctx.getDb() ? ctx.getDb()->getProfilingLevel() :
serverGlobalParams.defaultProfile;
// We'll now try to get the query executor that will execute this query for us. There
// are a few cases in which we know upfront which executor we should get and, therefore,
// we shortcut the selection process here.
@ -896,7 +897,7 @@ namespace mongo {
// Fill out curop based on query results. If we have a cursorid, we will fill out curop with
// this cursorid later.
long long ccId = 0;
endQueryOp(ctx, exec.get(), numResults, ccId, &curop);
endQueryOp(exec.get(), dbProfilingLevel, numResults, ccId, &curop);
if (shouldSaveCursor(txn, collection, state, exec.get())) {
// We won't use the executor until it's getMore'd.

View File

@ -71,11 +71,13 @@ namespace mongo {
/**
* Fills out CurOp with information regarding this query's execution.
*
* Uses explain functionality to extract stats from 'exec'. 'ctx' is used to conditionalize
* whether or not we do expensive stats gathering based on the database profiling level.
* Uses explain functionality to extract stats from 'exec'.
*
* The database profiling level, 'dbProfilingLevel', is used to conditionalize whether or not we
* do expensive stats gathering.
*/
void endQueryOp(const AutoGetCollectionForRead& ctx,
PlanExecutor* exec,
void endQueryOp(PlanExecutor* exec,
int dbProfilingLevel,
int numResults,
CursorId cursorId,
CurOp* curop);