Skip to content

Server-streaming call isn’t cancelled when client task is cancelled #17

@Obbut

Description

@Obbut

Describe the bug

Cancelling the client Task during a server-streaming RPC does not cancel the server-side handler: the server keeps successfully writing messages indefinitely. Neither Task.isCancelled nor context.cancellation.isCancelled becomes true during the call. Cancellation is only observed much later (when the graceful shutdown of the server starts).

Versions:

  • grpc-swift: grpc-swift-2 v2.1.0 (GRPCCore, GRPCInProcessTransport)
  • protoc-gen-grpc-swift: v2.1.1 (grpc-swift-protobuf)
  • swift-protobuf: v1.31.0
  • Swift: Swift version 6.1 (swift-6.1-RELEASE), Target: aarch64-unknown-linux-gnu
  • Platform: Ubuntu 24.04.2 LTS (Dev Container); also reproduces on macOS
  • Build: swift run (debug)
  • Transport: In-process (GRPCInProcessTransport)

We are experiencing this issue when using the Swift NIO based HTTP2 transport as well. In our production code, we have a set-up with an iOS app, that connects over gRPC to a backend ("app API"), which in turn connects to another backend over gRPC ("core API"). The entire codebase is built with GRPC Swift 2 (server and client). We're noticing that streams that are closed by the app aren't properly cancelled on the App API or Core API.

To reproduce

git clone https://github.com/Obbut/GRPC-Swift-2-cancellation.git
cd GRPC-Swift-2-cancellation
swift run

The repro project makes 3 requests to a server streaming RPC in series. Each request is cancelled (by cancelling the Task) before starting the next.

As should be evident by observing the logs, the cancellation is not correctly propagated to the server. The writer keeps succeeding.

Expected behaviour

  • The server‑side handler observes cancellation promptly.
  • writer.write(...) throws or the handler exits quickly.
  • context.cancellation.isCancelled and/or Task.isCancelled becomes true for that call.
  • Per‑call resources are released (e.g., the activeWriters in the repro project returns to zero between calls).

Additional information

Repro project, main file: https://github.com/Obbut/GRPC-Swift-2-cancellation/blob/c597dc35930193a45cafb0addaba547037118158/Sources/GRPCSwift2Cancellation/main.swift
Repro project, service implementation: https://github.com/Obbut/GRPC-Swift-2-cancellation/blob/main/Sources/GRPCSwift2Cancellation/HelloWorldService.swift

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions