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
Threading issue with CallRouter. #256
Comments
Thanks @TheSatoshiChiba, I think this is ok. The rule for threading with NSubstitute is that a substitute must be configured on a single thread, but should be callable from multiple threads. AFAICT this only affects configuration? |
What about assertions? What is the threading rule on those? Because this issue would only allow assertions (checking for received calls) on a single thread. So it doesn't only affect configuration. It affects scenarios where you would have calls on the substituted object in one thread while trying to assert them in another at roughly the same time. If the usage of the library is intended to be single threaded for setup and assertion then it should be clearly documented. |
Yes assertions should also be check by a single thread at a time. NSubstitute's syntax means some unavoidable race conditions, such as a call happening between Good suggestion about documenting this. Do you think this should just be a "Threading" sub-page on http://nsubstitute.github.io/help.html ? |
Yes a threading sub-page that outlines the model seems like a sensible idea. Thank you 👍 |
Hi @TheSatoshiChiba, |
Looks good to me. Thank you :) |
CallRouter is not thread-safe because it allows mutation between SetSate(...) and Route(...). See for example: public static T Received(...) in SubstituteExtensions:
Another thread could call SetRoute(...) directly after it has been called within Received(...) which would lead to a current route mutation and therefore unexpected or erroneous behaviour. Consider the following scenario:
This test will sometimes fail within the Dispatcher when calling LastCall(...); because it is using the same Route as callback.Received( i + 1 ). Easy to very if catching the ReceivedCallsException in CallRouter.Route() around return routeToUseForThisCall.Handle( call );
A possible fix would be to attach the call route to the currently issued call of the substitute and making the CallRoute class immutable. I know I could change my tests to work around this issue but I think this library should be robust and safe to use from any number of threads.
I would be happy to submit a pull-request but I wanted to hear your thoughts on this issue first before starting any work on a possible patch.
The text was updated successfully, but these errors were encountered: