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

ObjectDisposedException: Request has finished and HttpContext disposed. in Extensions.Http.AspNetCore #2417

Open
pregress opened this issue Apr 19, 2024 · 4 comments
Labels
area: http Items related to experience improvements for HTTP triggers needs-investigation potential-bug Items opened using the bug report template, not yet triaged and confirmed as a bug

Comments

@pregress
Copy link

Description

When using the Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore version 1.2.1 we sometimes receive an ObjectDisposedException resulting in a System.InvalidOperationException: An attempt was made to transition a task to a final state when it had already completed.

Here is the stack trace of the ObjectDisposedException

Result: Failure Exception: System.ObjectDisposedException: Request has finished and HttpContext disposed. Object name: 'HttpContext'. at Microsoft.AspNetCore.Http.DefaultHttpContext.ThrowContextDisposed() at Microsoft.AspNetCore.Routing.RoutingHttpContextExtensions.GetRouteData(HttpContext httpContext) at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:line 54 at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 77 at Microsoft.Azure.Functions.Worker.Handlers.InvocationHandler.InvokeAsync(InvocationRequest request) in D:\a_work\1\s\src\DotNetWorker.Grpc\Handlers\InvocationHandler.cs:line 88 Stack: at Microsoft.AspNetCore.Http.DefaultHttpContext.ThrowContextDisposed() at Microsoft.AspNetCore.Routing.RoutingHttpContextExtensions.GetRouteData(HttpContext httpContext) at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:line 54 at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 77 at Microsoft.Azure.Functions.Worker.Handlers.InvocationHandler.InvokeAsync(InvocationRequest request) in D:\a_work\1\s\src\DotNetWorker.Grpc\Handlers\InvocationHandler.cs:line 88

This file hase already been changed, so line numbers are wrong. https://github.com/Azure/azure-functions-dotnet-worker/pull/2322/files/6149e16e951188e97bf7fcff6918b45ae233bde4#diff-dc49550c24c24c88566ae78776b0400d415dfc8d1a5d623571903671a953e715

The GetRouteData call in now on line 72 instead of 54.

We don't have a reproducible sample as this exception did only happens seemingly random.

As a quick fix we removed AspNetCore package from our function.

Steps to reproduce

Only saw it on a deployed linux azure function with a single instance.

@pregress pregress added the bug Something isn't working label Apr 19, 2024
@liliankasem liliankasem added needs-investigation potential-bug Items opened using the bug report template, not yet triaged and confirmed as a bug and removed bug Something isn't working labels Apr 19, 2024
@liliankasem
Copy link
Member

We don't have a reproducible sample as this exception did only happens seemingly random.

Can you share what you have and what you're currently doing? Even if it's random it would be helpful to have some steps that could help us figure out what is causing this.

@pregress
Copy link
Author

csproj file:

<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<TargetFramework>net8.0</TargetFramework>
		<AzureFunctionsVersion>v4</AzureFunctionsVersion>
		<OutputType>Exe</OutputType>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
		<PublishReadyToRun>true</PublishReadyToRun>
	</PropertyGroup>
  <ItemGroup>
	  <FrameworkReference Include="Microsoft.AspNetCore.App" />
	  <PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.1" />
	  <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
	  <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
	  <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.1" />
	  <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="5.17.0" />
	  <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.0" />
	  <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.2" />
	  <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
	  <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
	  <PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="8.0.0" />
	  <PackageReference Include="AspNetCore.HealthChecks.Publisher.ApplicationInsights" Version="8.0.0" />
	  <PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="8.0.0" />
	  <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
	  <PackageReference Include="Worker.Extensions.HttpTelemetryProcessor" Version="1.0.2" />
  </ItemGroup>

  <ItemGroup>
    <None Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <None Update="appsettings.Production.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="appsettings.Staging.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
	<None Update="local.settings.json">
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <CopyToPublishDirectory>Never</CopyToPublishDirectory>
	</None>
  </ItemGroup>
  <PropertyGroup>
    <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
  </PropertyGroup>
	<ItemGroup>
		<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
	</ItemGroup>
</Project>

Trimmed down function raising object desposed function:

public class BrokenFunction(IRequestProcessor requestProcessor,
    IRequestReader requestReader, IAuthenticationService authenticationService,
    ILogger<BrokenFunction> logger) : AuthorizedFunction(authenticationService)
{
    [Function("BrokenFunction")]
    public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest httpRequest, ExecutionContext executionContext)
    {
        var result = await AuthorizeAsync(httpRequest);
        if (!result.Succeeded)
        {
            logger.LogWarning(result.Failure, "Unauthenticated request");
            return new UnauthorizedResult();
        }

        try
        {
            var request = await requestReader.ReadRequest(logger, httpRequest);
            using var scope = logger.BeginScope(new Dictionary<string, object>
            {
                ["RequestId"] = request.RequestId,
                ["Email"] = httpRequest.HttpContext.User.FindFirst(ClaimTypes.Email)?.Value,
                ["CustomerId"] = httpRequest.HttpContext.User.FindFirst("customer_id")?.Value,
            });
            var response = await requestProcessor.ProcessRequest(logger, request);
            var serializerSettings = SerializerSettings.GetSettings();
            var jsonResponse = JsonConvert.SerializeObject(response, serializerSettings);
            logger.LogInformation("response: {json}", jsonResponse);
            return new OkObjectResult(response);
        }
        catch (UnauthorizedAccessException)
        {
            return new UnauthorizedResult();
        }
    }
}

public abstract class AuthorizedFunction(IAuthenticationService authenticationService)
{
    protected async Task<AuthenticateResult> AuthorizeAsync(HttpRequest httpRequest)
    {
        var result = await authenticationService.AuthenticateAsync(httpRequest.HttpContext, null);
        if (result.Succeeded)
        {
            httpRequest.HttpContext.User = result.Principal;
        }

        return result;
    }
}

Behind the scenes some other api's are being called. They can be slow, but we could not correlate duration vs ObjectDisposedexception.

@Rihab8
Copy link

Rihab8 commented Jul 1, 2024

Hi , I got the similar exception,

Result: Function 'LaunchSubscriptionInstance', Invocation id 'c822cd42-d803-408c-9556-294a93a21f24': An exception was thrown by the invocation.
Exception: System.ObjectDisposedException: Request has finished and HttpContext disposed.
Object name: 'HttpContext'.
   at Microsoft.AspNetCore.Http.DefaultHttpContext.ThrowContextDisposed()
   at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Features()
   at Microsoft.AspNetCore.Routing.RoutingHttpContextExtensions.GetRouteData(HttpContext httpContext)
   at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:line 54
   at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 89
Stack:    at Microsoft.AspNetCore.Http.DefaultHttpContext.ThrowContextDisposed()
   at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Features()
   at Microsoft.AspNetCore.Routing.RoutingHttpContextExtensions.GetRouteData(HttpContext httpContext)
   at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:line 54
   at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 89

when we can expect the issue fix ? and is there any short term solution or workaround for this issue

@pregress
Copy link
Author

pregress commented Jul 1, 2024

@Rihab8 We removed the dependencies to Asp.net, depending on your functions this is a viable solution or not.
If you don't have the asp.net pipeline everything works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: http Items related to experience improvements for HTTP triggers needs-investigation potential-bug Items opened using the bug report template, not yet triaged and confirmed as a bug
Projects
None yet
Development

No branches or pull requests

3 participants