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

Crash on page reload (Pressing F5) in ASP.Net.Core 2.2 while using Unity container #1301

Closed
ENikS opened this issue Mar 23, 2019 · 11 comments · Fixed by #2236
Closed

Crash on page reload (Pressing F5) in ASP.Net.Core 2.2 while using Unity container #1301

ENikS opened this issue Mar 23, 2019 · 11 comments · Fixed by #2236
Milestone

Comments

@ENikS
Copy link

ENikS commented Mar 23, 2019

Describe the bug

Calling disposed service provider on refresh.

While using Unity as a Service Provider, loading a page the first time runs fine but on refresh, hitting F5, this exception is thrown.

To Reproduce

Steps to reproduce the behavior:

  1. Create new ASP.Net.Core 2.2 app
  2. Add Unity provider as suggested here. Reference Unity.Microsoft.DependencyInjection v5.10.0 because I've disabled Dispose method in latest as a temporary workaround for the issue.
  3. Run
  4. Hit F5

This example reproduces the behavior. It was working fine with previous releases.

Additional context

The instance of service provider is released by this line

The stack at the moment of Dispose call:

Unity.Microsoft.DependencyInjection.dll!Unity.Microsoft.DependencyInjection.ServiceProvider.Dispose() Line 78	C#
Microsoft.AspNetCore.Hosting.dll!Microsoft.AspNetCore.Hosting.Internal.RequestServicesFeature.Dispose() Line 51	C#
Microsoft.AspNetCore.Http.Abstractions.dll!Microsoft.AspNetCore.Http.HttpResponse..cctor.AnonymousMethod__30_1(object disposable) Line 19	C#
Microsoft.AspNetCore.Server.IIS.dll!Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.FireOnCompleted() Line 448	C#
Microsoft.AspNetCore.Server.IIS.dll!Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT<Microsoft.AspNetCore.Hosting.Internal.HostingApplication.Context>.ProcessRequestAsync() Line 58	C#
Microsoft.AspNetCore.Server.IIS.dll!Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer.HandleRequest(Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext context) Line 176	C#
Microsoft.AspNetCore.Server.IIS.dll!Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer.HandleRequest.AnonymousMethod__26_0(object state) Line 160	C#
System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)	Unknown
System.Private.CoreLib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()	Unknown

the offending call to disposed ServiceProvider is coming from here. The stack at the moment of call as follows:

Unity.Microsoft.DependencyInjection.dll!Unity.Microsoft.DependencyInjection.ServiceProvider.GetService(System.Type serviceType) Line 31	C#
Microsoft.Extensions.DependencyInjection.Abstractions.dll!Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(System.IServiceProvider provider, System.Type serviceType) Line 56	C#
Microsoft.Extensions.DependencyInjection.Abstractions.dll!Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<Microsoft.AspNetCore.Routing.IEndpointAddressScheme<Microsoft.AspNetCore.Routing.RouteValuesAddress>>(System.IServiceProvider provider) Line 79	C#
Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Routing.DefaultLinkGenerator.GetEndpoints<Microsoft.AspNetCore.Routing.RouteValuesAddress>(Microsoft.AspNetCore.Routing.RouteValuesAddress address) Line 196	C#
Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Routing.DefaultLinkGenerator.GetPathByAddress<Microsoft.AspNetCore.Routing.RouteValuesAddress>(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.RouteValuesAddress address, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteValueDictionary ambientValues, Microsoft.AspNetCore.Http.PathString? pathBase, Microsoft.AspNetCore.Http.FragmentString fragment, Microsoft.AspNetCore.Routing.LinkOptions options) Line 81	C#
Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Routing.LinkGeneratorRouteValuesAddressExtensions.GetPathByRouteValues(Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string routeName, object values, Microsoft.AspNetCore.Http.PathString? pathBase, Microsoft.AspNetCore.Http.FragmentString fragment, Microsoft.AspNetCore.Routing.LinkOptions options) Line 46	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Routing.EndpointRoutingUrlHelper.Action(Microsoft.AspNetCore.Mvc.Routing.UrlActionContext urlActionContext) Line 84	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.UrlHelperExtensions.Action(Microsoft.AspNetCore.Mvc.IUrlHelper helper, string action, string controller, object values, string protocol, string host, string fragment) Line 215	C#
Microsoft.AspNetCore.Mvc.ViewFeatures.dll!Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGenerator.GenerateActionLink(Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext, string linkText, string actionName, string controllerName, string protocol, string hostname, string fragment, object routeValues, object htmlAttributes) Line 155	C#
Microsoft.AspNetCore.Mvc.TagHelpers.dll!Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Process(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output) Line 280	C#
Microsoft.AspNetCore.Razor.dll!Microsoft.AspNetCore.Razor.TagHelpers.TagHelper.ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output) Line 56	C#
Microsoft.AspNetCore.Razor.Runtime.dll!Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.RunAsync(Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext executionContext) Line 43	C#
ASP.Net.Core.Unity.Example.Views.dll!AspNetCore.Views_Shared__Layout.ExecuteAsync.AnonymousMethod__44_1()	C#
Microsoft.AspNetCore.Razor.Runtime.dll!Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync() Line 263	C#
ASP.Net.Core.Unity.Example.Views.dll!AspNetCore.Views_Shared__Layout.ExecuteAsync()	Unknown
System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<System.__Canon>(ref System.__Canon stateMachine)	Unknown
ASP.Net.Core.Unity.Example.Views.dll!AspNetCore.Views_Shared__Layout.ExecuteAsync()	Unknown
Microsoft.AspNetCore.Mvc.Razor.dll!Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(Microsoft.AspNetCore.Mvc.Razor.IRazorPage page, Microsoft.AspNetCore.Mvc.Rendering.ViewContext context) Line 178	C#
Microsoft.AspNetCore.Mvc.Razor.dll!Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(Microsoft.AspNetCore.Mvc.Razor.IRazorPage page, Microsoft.AspNetCore.Mvc.Rendering.ViewContext context, bool invokeViewStarts) Line 157	C#
Microsoft.AspNetCore.Mvc.Razor.dll!Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderLayoutAsync(Microsoft.AspNetCore.Mvc.Rendering.ViewContext context, Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewBufferTextWriter bodyWriter) Line 264	C#
Microsoft.AspNetCore.Mvc.Razor.dll!Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(Microsoft.AspNetCore.Mvc.Rendering.ViewContext context) Line 115	C#
Microsoft.AspNetCore.Mvc.ViewFeatures.dll!Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext, string contentType, int? statusCode) Line 247	C#
Microsoft.AspNetCore.Mvc.ViewFeatures.dll!Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ViewEngines.IView view, Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary viewData, Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionary tempData, string contentType, int? statusCode) Line 193	C#
Microsoft.AspNetCore.Mvc.ViewFeatures.dll!Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.ViewResult result) Line 171	C#
Microsoft.AspNetCore.Mvc.ViewFeatures.dll!Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) Line 67	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(Microsoft.AspNetCore.Mvc.IActionResult result) Line 138	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext<Microsoft.AspNetCore.Mvc.Filters.IResultFilter, Microsoft.AspNetCore.Mvc.Filters.IAsyncResultFilter>(ref Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.State next, ref Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Scope scope, ref object state, ref bool isCompleted) Line 1046	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync<Microsoft.AspNetCore.Mvc.Filters.IResultFilter, Microsoft.AspNetCore.Mvc.Filters.IAsyncResultFilter>() Line 1092	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext<Microsoft.AspNetCore.Mvc.Filters.IResultFilter, Microsoft.AspNetCore.Mvc.Filters.IAsyncResultFilter>(ref Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.State next, ref Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Scope scope, ref object state, ref bool isCompleted) Line 984	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters() Line 851	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.State next, ref Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Scope scope, ref object state, ref bool isCompleted) Line 709	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() Line 793	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.State next, ref Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Scope scope, ref object state, ref bool isCompleted) Line 407	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() Line 123	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() Line 81	C#
Microsoft.AspNetCore.Mvc.Core.dll!Microsoft.AspNetCore.Mvc.Internal.MvcEndpointDataSource.CreateEndpoint.AnonymousMethod__0(Microsoft.AspNetCore.Http.HttpContext context) Line 560	C#
Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext httpContext) Line 42	C#
Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext httpContext) Line 78	C#
Microsoft.AspNetCore.CookiePolicy.dll!Microsoft.AspNetCore.CookiePolicy.CookiePolicyMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext context) Line 43	C#
Microsoft.AspNetCore.StaticFiles.dll!Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext context) Line 139	C#
Microsoft.AspNetCore.Diagnostics.dll!Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext context)	Unknown
System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7>(ref Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7 stateMachine)	Unknown
Microsoft.AspNetCore.Diagnostics.dll!Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext context)	Unknown
Microsoft.AspNetCore.HostFiltering.dll!Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext context) Line 81	C#
Microsoft.AspNetCore.Hosting.dll!Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext httpContext) Line 47	C#
Microsoft.AspNetCore.Hosting.dll!Microsoft.AspNetCore.Hosting.Internal.HostingApplication.ProcessRequestAsync(Microsoft.AspNetCore.Hosting.Internal.HostingApplication.Context context) Line 46	C#
Microsoft.AspNetCore.Server.IIS.dll!Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT<Microsoft.AspNetCore.Hosting.Internal.HostingApplication.Context>.ProcessRequestAsync() Line 34	C#
Microsoft.AspNetCore.Server.IIS.dll!Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer.HandleRequest(Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext context) Line 176	C#
Microsoft.AspNetCore.Server.IIS.dll!Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer.HandleRequest.AnonymousMethod__26_0(object state) Line 160	C#
System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)	Unknown
System.Private.CoreLib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()	Unknown
@ENikS ENikS changed the title Crash on page reload (Pressing F5) Crash on page reload (Pressing F5) in ASP.Net.Core 2.2 Mar 25, 2019
@ENikS ENikS changed the title Crash on page reload (Pressing F5) in ASP.Net.Core 2.2 Crash on page reload (Pressing F5) in ASP.Net.Core 2.2 while using Unity container Apr 2, 2019
@davidfowl
Copy link
Member

@ENikS when I run this example https://github.com/unitycontainer/examples/tree/master/src/web/ASP.Net.Unity.Example, I get an ArgumentNullException:

Application startup exception: System.ArgumentNullException: Value cannot be null.
Parameter name: source
   at System.Linq.Enumerable.Reverse[TSource](IEnumerable`1 source)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
crit: Microsoft.AspNetCore.Hosting.Internal.WebHost[6]
      Application startup exception
System.ArgumentNullException: Value cannot be null.
Parameter name: source
   at System.Linq.Enumerable.Reverse[TSource](IEnumerable`1 source)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

Unhandled Exception: System.ArgumentNullException: Value cannot be null.
Parameter name: source
   at System.Linq.Enumerable.Reverse[TSource](IEnumerable`1 source)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.StartAsync(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String shutdownMessage)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
   at ASP.Net.Unity.Example.Program.Main(String[] args) in C:\dev\git\examples\src\web\ASP.Net.Unity.Example\Program.cs:line 23

@ENikS
Copy link
Author

ENikS commented Apr 9, 2019

Yes, when service provider is disposed the container reference is set to null. If you request a service from disposed provider it fails with NullReferenceException.

I will add a null check and throw an ObjectDisposedException instead.

@davidfowl
Copy link
Member

@ENikS this callstack is different from the issue you called out above. This happens at startup.

@ENikS
Copy link
Author

ENikS commented Apr 10, 2019

My apologies. It was running in Diagnostic mode.

I switched the mode in example and released new version of Unity.Microsoft.DependencyInjection. In new version (v5.10.2) Service Provider throws correct exception: ObjectDisposedException.

Please update example and try again.

@ENikS
Copy link
Author

ENikS commented Jun 21, 2019

@davidfowl

Did you find the cause for the issue?

I was considering spending some time and perhaps trying to solve the issue but was wandering if you would be willing to accept a PR with the fix.

If not, perhaps you could suggest what Unity should do to work around this problem? It is still broken and I can not release new version of the extension without doing something about this bug.

@analogrelay analogrelay added this to the Backlog milestone Jun 27, 2019
@davidfowl
Copy link
Member

@ENikS does the same repro work now?

@ENikS
Copy link
Author

ENikS commented Aug 26, 2019 via email

@davidfowl
Copy link
Member

I tried to run it and I get the same argument null exception. Do I need to update the example to 5.10.2?

@ENikS
Copy link
Author

ENikS commented Aug 26, 2019 via email

@davidfowl
Copy link
Member

davidfowl commented Aug 26, 2019

There's a bug in the container implementation that causes this issue. Here's the example. Even though Foo is a singleton, the service provider injected is from the first scope it's resolved from. That's a recipe for disaster. It's possible this bug was always there (it needs to be fixed ASAP if that's the case).

using System;
using Microsoft.Extensions.DependencyInjection;
using Unity;
using Unity.Microsoft.DependencyInjection;

namespace ASP.Net.Unity.Example
{
    public class Program
    {
        public class Foo
        {
            public Foo(IServiceProvider sp)
            {
                ServiceProvider = sp;
            }

            public IServiceProvider ServiceProvider { get; }
        }

        public static void Main(string[] args)
        {
            var container = new UnityContainer();
            var factory = new ServiceProviderFactory(container);
            var services = new ServiceCollection();
            services.AddSingleton<Foo>();
            var sp = factory.CreateServiceProvider(services);
            IServiceProvider scopedSp1 = null;
            IServiceProvider scopedSp2 = null;
            Foo foo1 = null;
            Foo foo2 = null;

            using (var scope1 = sp.CreateScope())
            {
                scopedSp1 = scope1.ServiceProvider;
                foo1 = scope1.ServiceProvider.GetRequiredService<Foo>();
            }

            using (var scope2 = sp.CreateScope())
            {
                scopedSp2 = scope2.ServiceProvider;
                foo2 = scope2.ServiceProvider.GetRequiredService<Foo>();
            }

            Console.WriteLine($"foo1.ServiceProvider == foo2.ServiceProvider = {foo1.ServiceProvider == foo2.ServiceProvider}");
            Console.WriteLine($"foo1.ServiceProvider == scopedSp1 = {foo1.ServiceProvider == scopedSp1}");
            Console.WriteLine($"foo2.ServiceProvider == scopedSp2 = {foo2.ServiceProvider == scopedSp2}");
        }
    }
}

UnityContainer:

foo1.ServiceProvider == foo2.ServiceProvider = True
foo1.ServiceProvider == scopedSp1 = True
foo2.ServiceProvider == scopedSp2 = False

DefaultContainer:

foo1.ServiceProvider == foo2.ServiceProvider = True
foo1.ServiceProvider == scopedSp1 = False
foo2.ServiceProvider == scopedSp2 = False

This should probably be part of our compat testing. I'll make sure we add that case.

@ENikS
Copy link
Author

ENikS commented Aug 26, 2019 via email

@ghost ghost locked as resolved and limited conversation to collaborators Dec 2, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants