-
Notifications
You must be signed in to change notification settings - Fork 11
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
Thread-affinity issue during async dispose fixed #35
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## develop #35 +/- ##
===========================================
+ Coverage 88.05% 90.62% +2.56%
===========================================
Files 5 5
Lines 134 96 -38
Branches 24 27 +3
===========================================
- Hits 118 87 -31
+ Misses 10 4 -6
+ Partials 6 5 -1
☔ View full report in Codecov by Sentry. |
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.
I think the concept here is right, but something needs to be done about the need for multiple threads to read at the same time. How does ASP.NET do this? That StackOverflow answer, while still valid, is 10 years old. Have new approaches come up in the meantime? Does the full ReaderWriterLock
have the same problems? Ideally we wouldn't take an additional dependency to solve this; perhaps ConcurrentDictionary
is enough? Of course, I think we had some ConcurrentDictionary
issues in core Autofac, something about it not getting properly disposed or hanging onto things incorrectly. I can't remember exactly right now.
IMO ConcurrentDictionary is by far the best option. I haven't came accross any issues with it so far. I played a bit with atomicity and at the end I favor optimistic concurrency approach that potentially creates new LifetimeScope and then disposes it when it cannot be added to dictionary in case of concurrent call. This should almost never happen. |
A trick with |
I haven't had a chance to come back and look at this yet, but it will probably involve looking at how we dealt with async disposal in core Autofac. I do remember there was some nature of locking required on the dictionary of disposables, to ensure disposal wasn't happening at the same time as resolution. I'd like to make sure similar things are captured here, like someone isn't trying to configure a tenant at the same time as disposal or something. So "no locks at all" isn't good, at least in the "clearing everything out" sense. I also remember there was something (might be this |
It also looks like with the removal of code here we're not passing the coverage check, which is going to block this. And that sucks, but it's there for a reason, so I'll have to look and see what's not covered and maybe suggest some tests to help boost the numbers. |
Disposal issue can be resolved using "is disposed" flag that disallows creating of new scope during and after disposal. See my next update. I use Interlocked here to ensure all threads has current version of the flag value. |
Lazy trick can be done, but it potentially locks concurrent threads. IMO the suggested change will perform better in this case. |
OK, I figured it out - it was |
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.
This is great, thanks! I'll see about getting a release out with this shortly.
Oh, bah, there's a build issue. |
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.
Minor analyzer issue blocking the build.
I fixed the field initializer, what should I do now? I don't see it... |
It's failing code coverage. If you look at the list of checks, you can see In particular, it looks like unit testing around the |
Ok I added some tests to increase the coverage. Now all checks are passing. |
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.
Thanks for this, and your patience getting through the hoops. We appreciate it! I'll try to get a 0.0.1 release out with this shortly.
Hello,
we encountered a bug when using IAsyncDisposable. It seems that MultitenantContainer's DisposeAsync wrongly uses ReaderWriterLockSlim in async context, because it internally compares locking and releasing thread ID. More here: https://stackoverflow.com/questions/19659387/readerwriterlockslim-and-async-await
According to aforementioned issue it seems to be the best option to use SemaphoreSlim instead of relying on custom or 3rd party implementation of AsyncReaderWriterLock.
Thank you in advance for merging.
N.