diff options
author | Maria van Keulen <maria@mongodb.com> | 2017-07-28 16:01:00 -0400 |
---|---|---|
committer | Maria van Keulen <maria@mongodb.com> | 2017-08-30 11:25:24 -0400 |
commit | 49708981947fbd44c0b8afa8c24b9c586c25091d (patch) | |
tree | 5d8cb68b670172d408425a10caf7b34aa728ed11 /src/mongo/db/concurrency | |
parent | 03055999749ed577af14d5d9cc969f616b4c3196 (diff) | |
download | mongo-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.cpp | 22 | ||||
-rw-r--r-- | src/mongo/db/concurrency/d_concurrency.h | 21 |
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(); /** |