-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fix ContentStore locking exceptions in async code #17246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
As expected, the test without fix results in this exception: I've applied the same change in The only remaining usage of Umbraco-CMS/src/Umbraco.Web.Common/Cache/HttpContextRequestAppCache.cs Lines 215 to 263 in 7787af2
|
bergmania
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good to me
* Add ContentCache test * Use SemaphoreSlim as write lock * Apply lock imrpovements to SnapDictionary * Obsolete unused MonitorLock (cherry picked from commit c3db345)
|
Awesome, let's verify whether this not only fixes the test, but also the runtime exceptions!👍🏻 Looking more into |
* Add ContentCache test * Use SemaphoreSlim as write lock * Apply lock imrpovements to SnapDictionary * Obsolete unused MonitorLock (cherry picked from commit c3db345)
Looking at the stack trace, the error happens in a notification handler (as notifications are published in the |
|
We are experiencing the same issue as user We can probably get round it by making the jobs run at different times, but it'd be good to understand the root cause here. I can reproduce the issue locally by triggering the two jobs together. Adding ICoreScopeProvider as in the documentation has not helped. |
|
@lauren-g-2025 After reviewing our code and verifying that we were not customizing the handler, we end up "workarounding" it. So basically: But going back to the main problem it is definitively this change. I hope this helps. |
|
@sauron Can you share the stack traces of the inner exceptions of that The write lock is enlisted in the current scope here: Umbraco-CMS/src/Umbraco.Infrastructure/Scoping/ScopeContextualBase.cs Lines 47 to 58 in fd9c1a0
If there's no scope, it will call the Umbraco-CMS/src/Umbraco.PublishedCache.NuCache/ContentStore.cs Lines 317 to 318 in ed0b236
Also, using
You might need to wrap the code in a Umbraco-CMS/src/Umbraco.Infrastructure/BackgroundJobs/Jobs/WebhookFiring.cs Lines 62 to 86 in fd9c1a0
@lauren-g-2025 Umbraco uses distributed write locks, so only a single write operation (like updating content) can be done at a time, so running 2 background jobs at the same isn't recommended for that reason alone. But otherwise, it seems like Hangfire executes jobs from the same thread, potentially causing issues with Umbraco contexts being shared between jobs, so the same |
|
Hey @ronaldbarendse , regarding this one did you guys manage to figure out what was the fix for this? Our use case is to automatically create, save and publish a child node after a node is created using notifications. It was working fine when we ran on Umbraco version 13.2.2. However, after upgrading to version 13.8.0, the recursive locks are not allowed error exceptions are happening even when there is no recursive locks. We notice this happens when multiple editors are creating and publishing on separate content nodes. Below is the stack trace that we received: We have tried adding scopes when we programmatically execute a Save and Publish but the issue still persists. Your help is much appreciated. Thanks in advance. |

Prerequisites
Description
After large Deploy operations (like an environment restore) has completed and the CMS tries to update the content cache (NuCache) as part of completing the Umbraco scope, the following exceptions were thrown:
This all originates from the
ContentStoreeither not 'seeing' it already has a write lock or getting a timeout when trying to get it (essentially deadlocking). Looking at the locking implementation in this class, it usesMonitor, which has the following requirement:But looking at the code and stack trace, the lock/monitor is entered and exited in different methods and they can potentially be called from different threads, which is especially likely if it contains async calls in-between them (Deploy heavily uses async and does more work in a single lock, further increasing the chances of exiting on a different thread).
I've added a test showcasing one of the exceptions and will push a fix that uses
SemaphoreSlim.