diff options
author | Muxi Yan <mxyan@google.com> | 2018-10-22 18:25:16 -0700 |
---|---|---|
committer | Muxi Yan <mxyan@google.com> | 2018-10-22 18:25:16 -0700 |
commit | e13c8678264d85353bb2ce49ae829c03f6c9493f (patch) | |
tree | 8b09b21775c64fc4888fdda395e8792d43a236e6 /src/objective-c/GRPCClient | |
parent | 3566540f16451ea87aff980b5de13c41a8debeb6 (diff) |
Do not issue more message when the call is canceled
Diffstat (limited to 'src/objective-c/GRPCClient')
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall.m | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 7e0640e8ae..23c8d0f2d7 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -104,6 +104,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_queue_t _dispatchQueue; /** Flags whether call has started. */ BOOL _started; + /** + * Flags that the call has been canceled. When this is true, pending initial metadata and message + * should not be issued to \a _handler. This ivar must be accessed with lock to self. + */ + BOOL _canceled; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions @@ -135,6 +140,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } dispatch_set_target_queue(responseHandler.dispatchQueue, _dispatchQueue); _started = NO; + _canceled = NO; } return self; @@ -217,6 +223,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; self->_pipe = nil; } if (self->_handler) { + @synchronized(self) { + self->_canceled = YES; + } id<GRPCResponseHandler> handler = self->_handler; dispatch_async(handler.dispatchQueue, ^{ if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { @@ -252,30 +261,50 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueInitialMetadata:(NSDictionary *)initialMetadata { - id<GRPCResponseHandler> handler = _handler; - if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedInitialMetadata:initialMetadata]; - }); + if (_handler != nil && initialMetadata != nil) { + id<GRPCResponseHandler> handler = _handler; + if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + dispatch_async(handler.dispatchQueue, ^{ + // Do not issue initial metadata if the call is already canceled. + __block BOOL canceled = NO; + @synchronized(self) { + canceled = self->_canceled; + } + if (!canceled) { + [handler receivedInitialMetadata:initialMetadata]; + } + }); + } } } - (void)issueMessage:(id)message { - id<GRPCResponseHandler> handler = _handler; - if ([handler respondsToSelector:@selector(receivedRawMessage:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedRawMessage:message]; - }); + if (_handler != nil && message != nil) { + id<GRPCResponseHandler> handler = _handler; + if ([handler respondsToSelector:@selector(receivedRawMessage:)]) { + dispatch_async(handler.dispatchQueue, ^{ + // Do not issue message if the call is already canceled. + __block BOOL canceled = NO; + @synchronized(self) { + canceled = self->_canceled; + } + if (!canceled) { + [handler receivedRawMessage:message]; + } + }); + } } } - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - id<GRPCResponseHandler> handler = _handler; - NSDictionary *trailers = _call.responseTrailers; - if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:trailers error:error]; - }); + if (_handler != nil) { + id<GRPCResponseHandler> handler = _handler; + NSDictionary *trailers = _call.responseTrailers; + if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:trailers error:error]; + }); + } } } |