From 02cd139770c7ad7716c951d8d93c3675164dbd2b Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Sat, 7 May 2022 12:06:33 +0200 Subject: [PATCH] Fixed issue with null reference when obtaining a lock using a detached scope. --- .../Scoping/IScopeProvider.cs | 4 +++- src/Umbraco.Infrastructure/Scoping/Scope.cs | 20 +++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Infrastructure/Scoping/IScopeProvider.cs b/src/Umbraco.Infrastructure/Scoping/IScopeProvider.cs index c29ce56a82..a41c64eb08 100644 --- a/src/Umbraco.Infrastructure/Scoping/IScopeProvider.cs +++ b/src/Umbraco.Infrastructure/Scoping/IScopeProvider.cs @@ -74,7 +74,9 @@ public interface IScopeProvider : ICoreScopeProvider /// A detached scope is not ambient and has no parent. /// It is meant to be attached by . /// - // TODO: This is not actually used apart from unit tests - I'm assuming it's maybe used by Deploy? + /// + /// This is not used by CMS but is used by Umbraco Deploy. + /// IScope CreateDetachedScope( IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, diff --git a/src/Umbraco.Infrastructure/Scoping/Scope.cs b/src/Umbraco.Infrastructure/Scoping/Scope.cs index f46ee443f8..190261a808 100644 --- a/src/Umbraco.Infrastructure/Scoping/Scope.cs +++ b/src/Umbraco.Infrastructure/Scoping/Scope.cs @@ -130,6 +130,8 @@ namespace Umbraco.Cms.Infrastructure.Scoping _fscope = fileSystems.Shadow(); } + _acquiredLocks = new Queue(); + return; } @@ -1204,7 +1206,14 @@ namespace Umbraco.Cms.Infrastructure.Scoping /// Lock object identifier to lock. /// TimeSpan specifying the timout period. private void ObtainReadLock(int lockId, TimeSpan? timeout) - => _acquiredLocks!.Enqueue(_scopeProvider.DistributedLockingMechanismFactory.DistributedLockingMechanism.ReadLock(lockId, timeout)); + { + if (_acquiredLocks == null) + { + throw new InvalidOperationException($"Cannot obtain a read lock as the {nameof(_acquiredLocks)} queue is null."); + } + + _acquiredLocks.Enqueue(_scopeProvider.DistributedLockingMechanismFactory.DistributedLockingMechanism.ReadLock(lockId, timeout)); + } /// /// Obtains a write lock with a custom timeout. @@ -1212,6 +1221,13 @@ namespace Umbraco.Cms.Infrastructure.Scoping /// Lock object identifier to lock. /// TimeSpan specifying the timout period. private void ObtainWriteLock(int lockId, TimeSpan? timeout) - => _acquiredLocks!.Enqueue(_scopeProvider.DistributedLockingMechanismFactory.DistributedLockingMechanism.WriteLock(lockId, timeout)); + { + if (_acquiredLocks == null) + { + throw new InvalidOperationException($"Cannot obtain a write lock as the {nameof(_acquiredLocks)} queue is null."); + } + + _acquiredLocks.Enqueue(_scopeProvider.DistributedLockingMechanismFactory.DistributedLockingMechanism.WriteLock(lockId, timeout)); + } } }