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

Async HTTP Trigger Function Does Not Cancel Cleanly #10739

Open
david-maw opened this issue Jan 14, 2025 · 0 comments
Open

Async HTTP Trigger Function Does Not Cancel Cleanly #10739

david-maw opened this issue Jan 14, 2025 · 0 comments

Comments

@david-maw
Copy link

An isolated async function with a CancellationToken parameter correctly sets IsCancelRequested when a client disconnects while the function is running but it also:

  1. Throws a TaskCancelled exception (which can be caught in the function)
  2. Even if it is caught, reports "An exception was thrown by the invocation"

I'm new to Azure Functions so I may have missed something obvious, but I'd expected to see IsCancelRequested set and nothing else (no exception unless I threw an uncaught one).

The test is simply to invoke the sample function below from a browser then cancel the request before it has chance to complete.

My sample Function code below is just the default code generated by VS with some minor additions.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace FunctionAppCancel
{
    public class Function1
    {
        private readonly ILogger<Function1> _logger;

        public Function1(ILogger<Function1> logger)
        {
            _logger = logger;
        }

        [Function("Function1")]
        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("C# HTTP trigger function processed a request.");
                await Task.Delay(5000, cancellationToken);

                if (cancellationToken.IsCancellationRequested)
                {
                    _logger.LogError("C# HTTP trigger function canceled.");
                    return new OkResult();
                }
                return new OkObjectResult("Welcome to Azure Functions!");
            }
            catch (Exception ex)
            {
                _logger.LogError($"C# HTTP trigger function threw exception {ex.Message}");
                return new BadRequestResult();
            }
        }
    }
}

The local emulator shows:

Azure Functions Core Tools
Core Tools Version:       4.0.6610 Commit hash: N/A +0d55b5d7efe83d85d2b5c6e0b0a9c1b213e96256 (64-bit)
Function Runtime Version: 4.1036.1.23224

[2025-01-14T00:56:41.615Z] Found H:\Develop\Samples\FunctionAppCancel\FunctionAppCancel\FunctionAppCancel.csproj. Using for user secrets file configuration.
[2025-01-14T00:56:43.806Z] Azure Functions .NET Worker (PID: 107448) initialized in debug mode. Waiting for debugger to attach...
[2025-01-14T00:56:43.841Z] Worker process started and initialized.

Functions:

        Function1: [GET,POST] http://localhost:7193/api/Function1

For detailed output, run func with --verbose flag.
[2025-01-14T00:56:48.886Z] Host lock lease acquired by instance ID '0000000000000000000000001BD189B9'.
[2025-01-14T00:56:52.633Z] Executing 'Functions.Function1' (Reason='This function was programmatically called via the host APIs.', Id=c0813456-e99e-4828-8b43-c2c6b28c97e6)
[2025-01-14T00:56:52.894Z] C# HTTP trigger function processed a request.
[2025-01-14T00:56:54.987Z] C# HTTP trigger function threw exception A task was canceled.
[2025-01-14T00:56:55.036Z] Function 'Function1', Invocation id 'c0813456-e99e-4828-8b43-c2c6b28c97e6': An exception was thrown by the invocation.
[2025-01-14T00:56:55.037Z] Result: Function 'Function1', Invocation id 'c0813456-e99e-4828-8b43-c2c6b28c97e6': An exception was thrown by the invocation.
Exception: System.ObjectDisposedException: Request has finished and HttpContext disposed.
[2025-01-14T00:56:55.038Z] Object name: 'HttpContext'.
[2025-01-14T00:56:55.039Z]    at Microsoft.AspNetCore.Http.DefaultHttpContext.ThrowContextDisposed()
[2025-01-14T00:56:55.040Z]    at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Features()
[2025-01-14T00:56:55.041Z]    at Microsoft.AspNetCore.Routing.RoutingHttpContextExtensions.GetRouteData(HttpContext httpContext)
[2025-01-14T00:56:55.042Z]    at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware.TryHandleHttpResult(Object result, FunctionContext context, HttpContext httpContext, Boolean isInvocationResult) in D:\a\_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:line 77
[2025-01-14T00:56:55.043Z]    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 56
[2025-01-14T00:56:55.044Z]    at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 96
Stack:    at Microsoft.AspNetCore.Http.DefaultHttpContext.ThrowContextDisposed()
[2025-01-14T00:56:55.045Z]    at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Features()
[2025-01-14T00:56:55.046Z]    at Microsoft.AspNetCore.Routing.RoutingHttpContextExtensions.GetRouteData(HttpContext httpContext)
[2025-01-14T00:56:55.046Z]    at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware.TryHandleHttpResult(Object result, FunctionContext context, HttpContext httpContext, Boolean isInvocationResult) in D:\a\_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:line 77
[2025-01-14T00:56:55.047Z]    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 56
[2025-01-14T00:56:55.048Z]    at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 96.
[2025-01-14T00:56:55.070Z] Executed 'Functions.Function1' (Failed, Id=c0813456-e99e-4828-8b43-c2c6b28c97e6, Duration=2463ms)
[2025-01-14T00:56:55.071Z] System.Private.CoreLib: Exception while executing function: Functions.Function1. Microsoft.Azure.WebJobs.Script.Grpc: Failed to proxy request with ForwarderError: RequestCanceled. System.Net.Http: The operation was canceled. System.Net.Sockets: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request.. The I/O operation has been aborted because of either a thread exit or an application request.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants