question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

OperationCanceledException thrown when canceling a CancelationToken does not reference the token canceled

See original GitHub issue

What version of gRPC and what language are you using?

Grpc.Net.Client v2.51.0, .NET C#, Blazor WebAssembly

What operating system (Linux, Windows,…) and version?

WebAssembly (browser) - .NET

What runtime / compiler are you using (e.g. .NET Core SDK version dotnet --info)

.NET SDK 7.0.2

What did you do?

If you cancel a CancelationToken provided to the gRPC client, the OperationCanceledException thrown does not reference the token.

Context: Many implementations use this pattern to “catch” the cancelation:

        catch (Exception e)
        {
            if (e is OperationCanceledException oce && oce.CancellationToken == cancellationToken)
            {
                // No-op; we canceled the operation, so it's fine to suppress this exception.
            }

e.g. Blazor’s Virtualize component: https://github.com/dotnet/aspnetcore/blob/dfab67748084f120472e634a975b3c45150f608b/src/Components/Web/src/Virtualization/Virtualize.cs#L378-L383

What did you expect to see?

  1. The OperationCanceledException.CancellationToken (in RpcException.DebugException) should be the original CancellationToken canceled.
  2. In case of cancellation, the OperationFailedException should not be wrapped by RpcException. It does not make sense as there is literally no use case where you would take advantage of having a RpcException instead of the very specific OperationCanceledException being caught by the caller expecting cancellation (such as Virtualize component in Blazor).

What did you see instead?

OperationCanceledException.CancellationToken is null. OperationCanceledException is masked by RpcException which implies need for “correcting” interceptor.

Anything else we should know about your project / environment?

I created a simple repro with Blazor-Virtualize. https://github.com/hakenr/VirtualizeGrpcRepro

The repro includes an active interceptor which “fixes” the error (for the AsyncUnaryCall): https://github.com/hakenr/VirtualizeGrpcRepro/blob/master/BlazorGrpcWebCodeFirst/Client/CancellationWorkaroundGrpcClientInterceptor.cs

If you remove the registration of CancellationWorkaroundGrpcClientInterceptor from BlazorGrpcWebCodeFirst.Client/Program.cs (line 18) you immediately see the result - the OperationFailedException not being caught by Virtualize, which breaks the app.

cc @JamesNK, @mgravell

Issue Analytics

  • State:closed
  • Created 8 months ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
JamesNKcommented, Jan 13, 2023

Ok. There is an internal CancellationTokenSource for each gRPC call. I think there is a way to cancel it so that the reported token is the original one. Might be able to fix this in the gRPC client so your workaround isn’t needed.

1reaction
JamesNKcommented, Jan 11, 2023

There is a ThrowOperationCanceledOnCancellation option on the gRPC channel.

I agree btw, but we chose to it this way for backwards compact with gRPC.Core

Read more comments on GitHub >

github_iconTop Results From Across the Web

Should a function allowed to throw ...
If the task that was canceled had an associated cancellation token, it is returned by the CancellationToken property, and the CancellationToken.
Read more >
CancellationToken.ThrowIfCancellationRequested Method
Throws a OperationCanceledException if this token has had cancellation requested.
Read more >
A Deep Dive into C#'s CancellationToken | by Mitesh Shah
Don't throw OperationCanceledException after you've completed the work, just because the token was signaled. Return a successful result and let ...
Read more >
Cancellation, Part 3: Detecting Cancellation
After issuing a cancellation request, detect whether the operation completed normally or was cancelled.
Read more >
Why Do You Need a Cancellation Token in C# for Tasks?
Complete Task via ThrowIfCancellationRequested() Method Call ... The thrown exception will appear as an InnerException of the AggregateException .
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found