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
-1
View File
@@ -27,7 +27,6 @@
-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks serverMajorVersion:(int)serverMajorVersion; -(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks serverMajorVersion:(int)serverMajorVersion;
-(void) terminate; -(void) terminate;
-(void) terminateInternal;
-(void) main; -(void) main;
@end @end
+18 -13
View File
@@ -23,6 +23,7 @@
int _serverMajorVersion; int _serverMajorVersion;
} }
static NSLock* initLock;
static OpusDecoder *opusDecoder; static OpusDecoder *opusDecoder;
static id<ConnectionCallbacks> _callbacks; static id<ConnectionCallbacks> _callbacks;
@@ -261,26 +262,28 @@ void ClDisplayTransientMessage(char* message)
[_callbacks displayTransientMessage: 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 -(void) terminate
{ {
// We're guaranteed to not be on a moonlight-common thread // We dispatch this async to get out because this can be invoked
// here so it's safe to call stop directly // on a thread inside common and we don't want to deadlock. It also avoids
LiStopConnection(); // 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 -(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks serverMajorVersion:(int)serverMajorVersion
{ {
self = [super init]; 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]; _host = [config.host cStringUsingEncoding:NSUTF8StringEncoding];
renderer = myRenderer; renderer = myRenderer;
_callbacks = callbacks; _callbacks = callbacks;
@@ -403,12 +406,14 @@ static OSStatus playbackCallback(void *inRefCon,
-(void) main -(void) main
{ {
[initLock lock];
LiStartConnection(_host, LiStartConnection(_host,
&_streamConfig, &_streamConfig,
&_clCallbacks, &_clCallbacks,
&_drCallbacks, &_drCallbacks,
&_arCallbacks, &_arCallbacks,
NULL, 0, _serverMajorVersion); NULL, 0, _serverMajorVersion);
[initLock unlock];
} }
@end @end
-1
View File
@@ -14,6 +14,5 @@
- (id) initWithConfig:(StreamConfiguration*)config renderView:(UIView*)view connectionCallbacks:(id<ConnectionCallbacks>)callback; - (id) initWithConfig:(StreamConfiguration*)config renderView:(UIView*)view connectionCallbacks:(id<ConnectionCallbacks>)callback;
- (void) stopStream; - (void) stopStream;
- (void) stopStreamInternal;
@end @end
-9
View File
@@ -91,20 +91,11 @@
[opQueue addOperation:_connection]; [opQueue addOperation:_connection];
} }
// This should NEVER be called from within a thread
// owned by moonlight-common
- (void) stopStream - (void) stopStream
{ {
[_connection terminate]; [_connection terminate];
} }
// This should only be called from within a thread
// owned by moonlight-common
- (void) stopStreamInternal
{
[_connection terminateInternal];
}
- (BOOL) launchApp:(HttpManager*)hMan { - (BOOL) launchApp:(HttpManager*)hMan {
HttpResponse* launchResp = [[HttpResponse alloc] init]; HttpResponse* launchResp = [[HttpResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:launchResp withUrlRequest: [hMan executeRequestSynchronously:[HttpRequest requestForResponse:launchResp withUrlRequest:
@@ -84,7 +84,7 @@
[self presentViewController:conTermAlert animated:YES completion:nil]; [self presentViewController:conTermAlert animated:YES completion:nil];
}); });
[_streamMan stopStreamInternal]; [_streamMan stopStream];
} }
- (void) stageStarting:(char*)stageName { - (void) stageStarting:(char*)stageName {
@@ -115,7 +115,7 @@
[self presentViewController:alert animated:YES completion:nil]; [self presentViewController:alert animated:YES completion:nil];
}); });
[_streamMan stopStreamInternal]; [_streamMan stopStream];
} }
- (void) launchFailed:(NSString*)message { - (void) launchFailed:(NSString*)message {