Deadlock fix for GRPCCall

pull/17578/head
Muxi Yan 6 years ago
parent d7650a841b
commit cf303c3ee7
  1. 47
      src/objective-c/GRPCClient/GRPCCall.m

@ -539,26 +539,24 @@ const char *kCFStreamVarName = "grpc_cfstream";
#pragma mark Finish #pragma mark Finish
// This function should support being called within a @synchronized(self) block in another function
// Should not manipulate _requestWriter for deadlock prevention.
- (void)finishWithError:(NSError *)errorOrNil { - (void)finishWithError:(NSError *)errorOrNil {
GRXConcurrentWriteable *copiedResponseWriteable = nil;
@synchronized(self) { @synchronized(self) {
if (_state == GRXWriterStateFinished) { if (_state == GRXWriterStateFinished) {
return; return;
} }
_state = GRXWriterStateFinished; _state = GRXWriterStateFinished;
copiedResponseWriteable = _responseWriteable;
if (errorOrNil) {
[_responseWriteable cancelWithError:errorOrNil];
} else {
[_responseWriteable enqueueSuccessfulCompletion];
}
// If the call isn't retained anywhere else, it can be deallocated now. // If the call isn't retained anywhere else, it can be deallocated now.
_retainSelf = nil; _retainSelf = nil;
} }
if (errorOrNil) {
[copiedResponseWriteable cancelWithError:errorOrNil];
} else {
[copiedResponseWriteable enqueueSuccessfulCompletion];
}
_requestWriter.state = GRXWriterStateFinished;
} }
- (void)cancel { - (void)cancel {
@ -572,19 +570,7 @@ const char *kCFStreamVarName = "grpc_cfstream";
userInfo:@{NSLocalizedDescriptionKey : @"Canceled by app"}]]; userInfo:@{NSLocalizedDescriptionKey : @"Canceled by app"}]];
[_wrappedCall cancel]; [_wrappedCall cancel];
} }
} _requestWriter.state = GRXWriterStateFinished;
- (void)maybeFinishWithError:(NSError *)errorOrNil {
BOOL toFinish = NO;
@synchronized(self) {
if (_finished == NO) {
_finished = YES;
toFinish = YES;
}
}
if (toFinish == YES) {
[self finishWithError:errorOrNil];
}
} }
- (void)dealloc { - (void)dealloc {
@ -647,6 +633,7 @@ const char *kCFStreamVarName = "grpc_cfstream";
}]]; }]];
[strongSelf->_wrappedCall cancel]; [strongSelf->_wrappedCall cancel];
} }
strongSelf->_requestWriter.state = GRXWriterStateFinished;
} else { } else {
@synchronized(strongSelf) { @synchronized(strongSelf) {
[strongSelf->_responseWriteable enqueueValue:data [strongSelf->_responseWriteable enqueueValue:data
@ -818,6 +805,7 @@ const char *kCFStreamVarName = "grpc_cfstream";
error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo]; error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
} }
[strongSelf finishWithError:error]; [strongSelf finishWithError:error];
strongSelf->_requestWriter.state = GRXWriterStateFinished;
} }
}]; }];
} }
@ -841,12 +829,12 @@ const char *kCFStreamVarName = "grpc_cfstream";
callOptions:_callOptions]; callOptions:_callOptions];
if (_wrappedCall == nil) { if (_wrappedCall == nil) {
[self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain [self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeUnavailable code:GRPCErrorCodeUnavailable
userInfo:@{ userInfo:@{
NSLocalizedDescriptionKey : NSLocalizedDescriptionKey :
@"Failed to create call or channel." @"Failed to create call or channel."
}]]; }]];
return; return;
} }
@ -971,6 +959,7 @@ const char *kCFStreamVarName = "grpc_cfstream";
NSLocalizedDescriptionKey : @"Connectivity lost." NSLocalizedDescriptionKey : @"Connectivity lost."
}]]; }]];
} }
strongSelf->_requestWriter.state = GRXWriterStateFinished;
} }
} }

Loading…
Cancel
Save