-
Notifications
You must be signed in to change notification settings - Fork 45
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
Use the new Castle.Core CaptureProceedInfo() to make AsyncInterceptor work for reals #54
Conversation
Codecov Report
@@ Coverage Diff @@
## master #54 +/- ##
==========================================
- Coverage 100% 98.26% -1.74%
==========================================
Files 5 5
Lines 230 231 +1
Branches 7 11 +4
==========================================
- Hits 230 227 -3
- Partials 0 4 +4
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master #54 +/- ##
========================================
+ Coverage 98.26% 100% +1.73%
========================================
Files 5 5
Lines 231 232 +1
Branches 11 11
========================================
+ Hits 227 232 +5
+ Partials 4 0 -4
Continue to review full report at Codecov.
|
a1dcb25
to
d15ff56
Compare
@JSkimming awesome work here! I have a lot on my plate atm. But, I will try to find time during the weekend helping out on this! |
fb02f30
to
b814ced
Compare
b814ced
to
ab1bb63
Compare
ab1bb63
to
74bd01c
Compare
@brunoblank Please do jump in if you can spare the time. I've made the changes and have managed to get it all working, unfortunately, I'm getting a deadlock unless I disable parallel test execution. If you edit the file xunit.runner.json on the use-CaptureProceedInfo branch and change Every 60 seconds the Long Running Tests are displayed. This shows the tests that are deadlocked. Change I'd like to bottom out the root cause of the deadlock. It's possible this is not a new problem but is now happening because all the tests are truly executing asynchronously. |
@JSkimming I tried to reproduce the dead-lock but everything seems to run fine for me done the changes described above. This is the output:
(dotnet --version: 2.2.105) |
Same here btw. No deadlocks for me during test execution with dotnet --info
dotnet test
|
@brunoblank, @stakx thanks for giving it a shot. I was using .NET Core 2.2.104 though now upgraded to 2.2.202, I still get the deadlock, as does both AppVeyor and Travis. I've noticed both of your test runs take a little over 2 seconds, whereas mine is about 3.8, maybe there's a timing issue, which my 2-year-old laptop gets because it's slower than yours. I'm going to see if I can identify where the deadlock is occurring. |
Moq also references Castle.Core, which may be confusing matters.
bb76566
to
8b7fe22
Compare
@brunoblank, @stakx I found it. xunit defaults
I was right; it was never a problem because async before interception wasn't possible. This deadlock issue does though highlight the flaw in the implementation of It's trying to make it easier to implement an interceptor by requiring a derived class to implement just two methods. protected abstract Task InterceptAsync(IInvocation invocation, Func<IInvocation, Task> proceed);
protected abstract Task<TResult> InterceptAsync<TResult>(
IInvocation invocation,
Func<IInvocation, Task<TResult>> proceed); But for synchronous interception, it has to transition back from a potentially asynchronous interceptor, and the only safe way (or so I thought) to do that is starting a new thread using In a real scenario, the maximum number of threads will be far higher, but not unlimited, and this has the potential to deadlock in a production system, something interception is not supposed to do. Sort of like the Hippocratic Oath 😃. I'm keen to get this out, so I'm thinking of releasing it as an alpha, then I'd like to tackle |
Glad you found it! That makes sense now when you identified it. We should remove all blocking calls from the library as it will cause thread exhaustion (or really bad performance when the thread pool is scaling up). It is important that we realize running synchronous (cpu-bound) interceptions is totally fine even if it return like The big problem is running blocking call on async or the slightly better running async and waiting (using a Task.Run). We should not try to safeguard against this.
Totally agree |
39058d3
to
7af5237
Compare
86f7b40
to
a81f2fc
Compare
I plan to release this as an alpha, as we feel some work is required before it is production ready.