From af5207262ff6c542b299ec91c82942c10baed174 Mon Sep 17 00:00:00 2001 From: Michael Lumish Date: Fri, 6 Aug 2021 11:11:30 -0700 Subject: [PATCH 1/2] grpc-js: Check for closed server stream before sending --- packages/grpc-js/package.json | 2 +- packages/grpc-js/src/server-call.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/grpc-js/package.json b/packages/grpc-js/package.json index 87a75d79..f0e20ff1 100644 --- a/packages/grpc-js/package.json +++ b/packages/grpc-js/package.json @@ -1,6 +1,6 @@ { "name": "@grpc/grpc-js", - "version": "1.3.6", + "version": "1.3.7", "description": "gRPC Library for Node - pure JS implementation", "homepage": "https://grpc.io/", "repository": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js", diff --git a/packages/grpc-js/src/server-call.ts b/packages/grpc-js/src/server-call.ts index aa8bd647..7d3fe192 100644 --- a/packages/grpc-js/src/server-call.ts +++ b/packages/grpc-js/src/server-call.ts @@ -429,7 +429,7 @@ export class Http2ServerCallStream< private checkCancelled(): boolean { /* In some cases the stream can become destroyed before the close event * fires. That creates a race condition that this check works around */ - if (this.stream.destroyed) { + if (this.stream.destroyed || this.stream.closed) { this.cancelled = true; } return this.cancelled; From ce2765f7fb1e5694a9990ee57f1142c1c87dcfa1 Mon Sep 17 00:00:00 2001 From: Michael Lumish Date: Fri, 6 Aug 2021 11:53:48 -0700 Subject: [PATCH 2/2] grpc-js: Handle errors thrown by writing to http2 stream --- packages/grpc-js/src/call-stream.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/grpc-js/src/call-stream.ts b/packages/grpc-js/src/call-stream.ts index 57693343..8d72bb3e 100644 --- a/packages/grpc-js/src/call-stream.ts +++ b/packages/grpc-js/src/call-stream.ts @@ -637,7 +637,15 @@ export class Http2CallStream implements Call { this.pendingWrite.length + ' (deferred)' ); - stream.write(this.pendingWrite, this.pendingWriteCallback); + try { + stream.write(this.pendingWrite, this.pendingWriteCallback); + } catch (error) { + this.endCall({ + code: Status.UNAVAILABLE, + details: `Write failed with error ${error.message}`, + metadata: new Metadata() + }); + } } this.maybeCloseWrites(); } @@ -762,7 +770,15 @@ export class Http2CallStream implements Call { this.pendingWriteCallback = cb; } else { this.trace('sending data chunk of length ' + message.message.length); - this.http2Stream.write(message.message, cb); + try { + this.http2Stream.write(message.message, cb); + } catch (error) { + this.endCall({ + code: Status.UNAVAILABLE, + details: `Write failed with error ${error.message}`, + metadata: new Metadata() + }); + } this.maybeCloseWrites(); } }, this.handleFilterError.bind(this));