summaryrefslogtreecommitdiff
path: root/src/mongo/db/concurrency
diff options
context:
space:
mode:
authorMaria van Keulen <maria@mongodb.com>2017-07-28 16:01:00 -0400
committerMaria van Keulen <maria@mongodb.com>2017-08-30 11:25:24 -0400
commit49708981947fbd44c0b8afa8c24b9c586c25091d (patch)
tree5d8cb68b670172d408425a10caf7b34aa728ed11 /src/mongo/db/concurrency
parent03055999749ed577af14d5d9cc969f616b4c3196 (diff)
downloadmongo-49708981947fbd44c0b8afa8c24b9c586c25091d.tar.gz
SERVER-29839 Protect from mid-command renames in parseNsOrUUID
Diffstat (limited to 'src/mongo/db/concurrency')
-rw-r--r--src/mongo/db/concurrency/d_concurrency.cpp22
-rw-r--r--src/mongo/db/concurrency/d_concurrency.h21
2 files changed, 38 insertions, 5 deletions
diff --git a/src/mongo/db/concurrency/d_concurrency.cpp b/src/mongo/db/concurrency/d_concurrency.cpp
index 42e7bb96d7f..d5d9fe1684c 100644
--- a/src/mongo/db/concurrency/d_concurrency.cpp
+++ b/src/mongo/db/concurrency/d_concurrency.cpp
@@ -152,6 +152,15 @@ Lock::GlobalLock::GlobalLock(OperationContext* opCtx,
_enqueue(lockMode, timeoutMs);
}
+Lock::GlobalLock::GlobalLock(GlobalLock&& otherLock)
+ : _opCtx(otherLock._opCtx),
+ _result(otherLock._result),
+ _pbwm(std::move(otherLock._pbwm)),
+ _isOutermostLock(otherLock._isOutermostLock) {
+ // Mark as moved so the destructor doesn't invalidate the newly-constructed lock.
+ otherLock._result = LOCK_INVALID;
+}
+
void Lock::GlobalLock::_enqueue(LockMode lockMode, unsigned timeoutMs) {
if (_opCtx->lockState()->shouldConflictWithSecondaryBatchApplication()) {
_pbwm.lock(MODE_IS);
@@ -200,8 +209,19 @@ Lock::DBLock::DBLock(OperationContext* opCtx, StringData db, LockMode mode)
invariant(LOCK_OK == _opCtx->lockState()->lock(_id, _mode));
}
+Lock::DBLock::DBLock(DBLock&& otherLock)
+ : _id(otherLock._id),
+ _opCtx(otherLock._opCtx),
+ _mode(otherLock._mode),
+ _globalLock(std::move(otherLock._globalLock)) {
+ // Mark as moved so the destructor doesn't invalidate the newly-constructed lock.
+ otherLock._mode = MODE_NONE;
+}
+
Lock::DBLock::~DBLock() {
- _opCtx->lockState()->unlock(_id);
+ if (_mode != MODE_NONE) {
+ _opCtx->lockState()->unlock(_id);
+ }
}
void Lock::DBLock::relockWithMode(LockMode newMode) {
diff --git a/src/mongo/db/concurrency/d_concurrency.h b/src/mongo/db/concurrency/d_concurrency.h
index 479dc84fb2a..44be439d539 100644
--- a/src/mongo/db/concurrency/d_concurrency.h
+++ b/src/mongo/db/concurrency/d_concurrency.h
@@ -83,8 +83,17 @@ public:
lock(mode);
}
+ ResourceLock(ResourceLock&& otherLock)
+ : _rid(otherLock._rid), _locker(otherLock._locker), _result(otherLock._result) {
+ // Mark as moved so the destructor doesn't invalidate the newly-
+ // constructed lock.
+ otherLock._result = LOCK_INVALID;
+ }
+
~ResourceLock() {
- unlock();
+ if (isLocked()) {
+ unlock();
+ }
}
void lock(LockMode mode);
@@ -174,6 +183,7 @@ public:
class EnqueueOnly {};
GlobalLock(OperationContext* opCtx, LockMode lockMode, unsigned timeoutMs);
+ GlobalLock(GlobalLock&&);
/**
* Enqueues lock but does not block on lock acquisition.
@@ -188,10 +198,12 @@ public:
EnqueueOnly enqueueOnly);
~GlobalLock() {
- if (isLocked() && _isOutermostLock) {
- _opCtx->recoveryUnit()->abandonSnapshot();
+ if (_result != LOCK_INVALID) {
+ if (isLocked() && _isOutermostLock) {
+ _opCtx->recoveryUnit()->abandonSnapshot();
+ }
+ _unlock();
}
- _unlock();
}
/**
@@ -268,6 +280,7 @@ public:
class DBLock {
public:
DBLock(OperationContext* opCtx, StringData db, LockMode mode);
+ DBLock(DBLock&&);
~DBLock();
/**