-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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 safety when using IExceptionHandlerFeature? #3177
Comments
I don't follow, await's are thread safe. You should only get corruption if you're accessing the same objects from different threads at the same time. The await stops operations on the first thread and transfers them to a new one, there's no concurrent execution. |
Yes. I understand there is no concurrent execution. However I was thinking the issue is that a memory barrier would be needed before reading from the It would not be an issue on x86 where there are strong memory model guarantees but I think it is an issue on x86_x64? I stumbled on this MSDN article which states the following:
Wouldn't that be a problem for the C# |
No, await is a memory barrier. This is also not the kind of behavior you'd get with dictionary corruption, they tend to go into infinite loops or throw odd exceptions. Even if you were to break one dictionary, it wouldn't spill over to another request, they're unique objects. It's completely plausible that identical exceptions are being thrown from your app for two requests. That's what I'd expect if the same thing went wrong twice. May makes you think those exceptions should have been different? |
I did not realize that Unfortunately I'm pretty sure the exceptions are the same. They're tagged with a UUID that we generate at random when sending requests to another server. When the exception occurs we serialize the request and put into the Thanks for your help. Much appreciated! |
Still do not know the source of this bug, but pretty sure it is not caused by the framework. |
I have code that use ASP.NET Core to implement a JSON API. In order to deal with errors it does something similar to this:
I noticed recently that under some circumstances the
exception
objects that were logged were identical. This occurred when the server was under load and similar exceptions were generated a few ms apart, so it made me think it was a concurrency issue.After some digging, I believe this problem occurs because access to the
IFeatureCollection
is not thread safe (see ApplicationInsights-aspnetcore #373), and because there is anawait
before retrieving the exception fromIFeatureCollection
.My understanding of concurrency bug is as follow:
ExceptionHandlerMiddleware
used byUseExceptionHandler()
catches the exception and sets it on the context (context.Features.Set<IExceptionHandlerFeature>(exceptionHandlerFeature)
)await
executed next. I believe this means the code that follows could potentially be executed in a different thread.context.Features.Get<IExceptionHandlerFeature>()?.Error
IFeatureCollection
is not thread safe, and it reads theIExceptionHandlerFeature
in a different thread from where it was written, I end up with corrupted data (i.e. the exception object from anotherHttpContext
)Does that make sense? Or am I just missing something obvious here? Unfortunately, I don't have definite proof. I was not able to reproduce the problem on a test server.
But if I am right, the whole
IExceptionHandlerFeature
being set inside theExceptionHandlerMiddleware
is kind of misleading. It would only safe to set features early on when theHttpContext
is being initialized, and not in the way it is done forIExceptionHandlerFeature
. It looks like theExceptionHandlerMiddleware
should be modified. Maybe it would be better if theException
object was given as a parameter of theExceptionHandler
callback?I decided to write my own
ErrorMiddleware
which is similar toExceptionHandlerMiddleware
but avoids using aDictionary
to capture the exception. I suppose I could have simply reordered the code and ensured thecontext.Features.Get<IExceptionHandlerFeature>()
was executed immediately, and not after the CORS workaround.The text was updated successfully, but these errors were encountered: