[Sandbox Broker] Fix deadlock and crash

The crash was because we weren't copying the results array before
iterating over it, and the deadlock was because this was forced to go
through the main thread, rather than going through its calling thread,
which could lock up if the main thread was busy working with the Sandbox
Broker object.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
lastfm
Christopher Snowhill 2022-06-24 14:58:56 -07:00
parent ec91f61403
commit 431849414f
1 changed files with 15 additions and 25 deletions

View File

@ -142,40 +142,30 @@ static SandboxBroker *kSharedSandboxBroker = nil;
return YES; return YES;
} }
static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_block_t block) {
if(dispatch_queue_get_label(queue) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) {
block();
} else {
dispatch_sync(queue, block);
}
}
- (SandboxEntry *)recursivePathTest:(NSURL *)url { - (SandboxEntry *)recursivePathTest:(NSURL *)url {
__block SandboxEntry *ret = nil; SandboxEntry *ret = nil;
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{ NSPersistentContainer *pc = [SandboxBroker sharedPersistentContainer];
NSPersistentContainer *pc = [SandboxBroker sharedPersistentContainer];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"path.length" ascending:NO]; NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"path.length" ascending:NO];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SandboxToken"]; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SandboxToken"];
request.sortDescriptors = @[sortDescriptor]; request.sortDescriptors = @[sortDescriptor];
NSError *error = nil; NSError *error = nil;
NSArray *results = [pc.viewContext executeFetchRequest:request error:&error]; NSArray *results = [pc.viewContext executeFetchRequest:request error:&error];
if(results) results = [results copy]; if(results) results = [results copy];
if(results && [results count] > 0) { if(results && [results count] > 0) {
for(SandboxToken *token in results) { for(SandboxToken *token in results) {
if(token.path && [SandboxBroker isPath:url aSubdirectoryOf:[NSURL fileURLWithPath:token.path]]) { if(token.path && [SandboxBroker isPath:url aSubdirectoryOf:[NSURL fileURLWithPath:token.path]]) {
SandboxEntry *entry = [[SandboxEntry alloc] initWithToken:token]; SandboxEntry *entry = [[SandboxEntry alloc] initWithToken:token];
ret = entry; ret = entry;
return; break;
}
} }
} }
}); }
if(ret) { if(ret) {
BOOL isStale; BOOL isStale;