Skip to content
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

Intermittent ArgumentNullException thrown in AutoTaskProvider #600

Closed
brianfeucht opened this issue Nov 27, 2019 · 3 comments · Fixed by #601
Closed

Intermittent ArgumentNullException thrown in AutoTaskProvider #600

brianfeucht opened this issue Nov 27, 2019 · 3 comments · Fixed by #601

Comments

@brianfeucht
Copy link

Describe the bug
I am seeing an intermittent ArgumentNullException thrown by the AutoTaskProvider in our test suite. The error moves around in our test suite, but it always has the same stacktrace:

System.ArgumentNullException : Value cannot be null.
Parameter name: source
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
   at NSubstitute.Routing.AutoValues.AutoTaskProvider.GetValue(Type type)
   at NSubstitute.Routing.Handlers.ReturnAutoValue.GetResultValueUsingProvider(ICall call, Type type, IAutoValueProvider provider)
   at NSubstitute.Routing.Handlers.ReturnAutoValue.Handle(ICall call)
   at NSubstitute.Routing.Route.Handle(ICall call)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleForwardingInterceptor.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.ObjectProxy_55.Read(Asset asset)

This behavior started after updating NSubstitute from 3.1.0 to 4.2.1

@alexandrnikitin
Copy link
Member

@brianfeucht Thank you for reporting the issue. After a quick look, I think it's a multithreading issue. Can you please confirm that you configure substitutes in multiple threads? We have a note for multithreading https://nsubstitute.github.io/help/threading/ I would also link some relevant issues and discussions #260

@alexandrnikitin
Copy link
Member

As for internals, here's a relevant commit that changes AutoValueProviders 6087233

The initialization is Lazy and set to LazyThreadSafetyMode.None, see the code

from the docs

(For None) The Lazy instance is not thread safe; if the instance is accessed from multiple threads, its behavior is undefined. Use this mode only when high performance is crucial and the Lazy instance is guaranteed never to be initialized from more than one thread.

@zvirja Can we remove LazyThreadSafetyMode.None from the constructor? Hopefully that will fix the issue.

@brianfeucht
Copy link
Author

@alexandrnikitin Thank you for the documentation. We are running most our tests in parallel via NUnit Console Runner. I'll be sure to audit the places we are seeing the exception bubble up to make sure we are configuring NSubstitute outside of test execution to avoid issues. FWIW this is the only case we have run into issues with threading.

It seems like that LazyThreadSafetyMode should be either PublicationOnly or ExecutionAndPublication if the long term goal is to support better thread safety. The AutoValueProvidersFactory constructor is an interesting pattern as it creates a self referencing loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants