Lock around LiStartConnection() and LiStopConnection() to fix thread-safety issues. This will hopefully address the crashes seen in 1.0.3 and 1.0.4.

This commit is contained in:
Cameron Gutman
2016-04-12 00:50:59 -04:00
parent 983c65d399
commit 1783abec13
5 changed files with 20 additions and 26 deletions

View File

@@ -27,7 +27,6 @@
-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks serverMajorVersion:(int)serverMajorVersion;
-(void) terminate;
-(void) terminateInternal;
-(void) main;
@end

View File

@@ -23,6 +23,7 @@
int _serverMajorVersion;
}
static NSLock* initLock;
static OpusDecoder *opusDecoder;
static id<ConnectionCallbacks> _callbacks;
@@ -261,26 +262,28 @@ void ClDisplayTransientMessage(char* message)
[_callbacks displayTransientMessage: message];
}
-(void) terminateInternal
{
// We dispatch this async to get out because this can be invoked
// on a thread inside common and we don't want to deadlock
dispatch_async(dispatch_get_main_queue(), ^{
// This is safe to call even before LiStartConnection
LiStopConnection();
});
}
-(void) terminate
{
// We're guaranteed to not be on a moonlight-common thread
// here so it's safe to call stop directly
LiStopConnection();
// We dispatch this async to get out because this can be invoked
// on a thread inside common and we don't want to deadlock. It also avoids
// blocking on the caller's thread waiting to acquire initLock.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[initLock lock];
LiStopConnection();
[initLock unlock];
});
}
-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks serverMajorVersion:(int)serverMajorVersion
{
self = [super init];
// Use a lock to ensure that only one thread is initializing
// or deinitializing a connection at a time.
if (initLock == nil) {
initLock = [[NSLock alloc] init];
}
_host = [config.host cStringUsingEncoding:NSUTF8StringEncoding];
renderer = myRenderer;
_callbacks = callbacks;
@@ -403,12 +406,14 @@ static OSStatus playbackCallback(void *inRefCon,
-(void) main
{
[initLock lock];
LiStartConnection(_host,
&_streamConfig,
&_clCallbacks,
&_drCallbacks,
&_arCallbacks,
NULL, 0, _serverMajorVersion);
[initLock unlock];
}
@end

View File

@@ -14,6 +14,5 @@
- (id) initWithConfig:(StreamConfiguration*)config renderView:(UIView*)view connectionCallbacks:(id<ConnectionCallbacks>)callback;
- (void) stopStream;
- (void) stopStreamInternal;
@end

View File

@@ -91,20 +91,11 @@
[opQueue addOperation:_connection];
}
// This should NEVER be called from within a thread
// owned by moonlight-common
- (void) stopStream
{
[_connection terminate];
}
// This should only be called from within a thread
// owned by moonlight-common
- (void) stopStreamInternal
{
[_connection terminateInternal];
}
- (BOOL) launchApp:(HttpManager*)hMan {
HttpResponse* launchResp = [[HttpResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:launchResp withUrlRequest:

View File

@@ -84,7 +84,7 @@
[self presentViewController:conTermAlert animated:YES completion:nil];
});
[_streamMan stopStreamInternal];
[_streamMan stopStream];
}
- (void) stageStarting:(char*)stageName {
@@ -115,7 +115,7 @@
[self presentViewController:alert animated:YES completion:nil];
});
[_streamMan stopStreamInternal];
[_streamMan stopStream];
}
- (void) launchFailed:(NSString*)message {