Sandbox Broker: Fix hang with synchronization

Synchronize with dispatches to the main thread instead of using
synchronization primitives. This prevents the main thread from
hanging another thread as a result of other threads entering the
sync block, then dispatching a callback to the main thread, which
also tries to lock on the sync block.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
main
Christopher Snowhill 2022-11-04 21:12:06 -07:00
parent 4bed0af868
commit 445b1bb295
No known key found for this signature in database
1 changed files with 21 additions and 18 deletions

View File

@ -221,10 +221,10 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
- (void)addFolderIfMissing:(NSURL *)folderUrl { - (void)addFolderIfMissing:(NSURL *)folderUrl {
if(![folderUrl isFileURL]) return; if(![folderUrl isFileURL]) return;
@synchronized (self) { dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
SandboxEntry *_entry = nil; SandboxEntry *_entry = nil;
for(SandboxEntry *entry in storage) { for(SandboxEntry *entry in self->storage) {
if(entry.path && entry.isFolder && [SandboxBroker isPath:folderUrl aSubdirectoryOf:[NSURL fileURLWithPath:entry.path]]) { if(entry.path && entry.isFolder && [SandboxBroker isPath:folderUrl aSubdirectoryOf:[NSURL fileURLWithPath:entry.path]]) {
_entry = entry; _entry = entry;
break; break;
@ -255,7 +255,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
} }
}]; }];
} }
} });
} }
- (void)addFileIfMissing:(NSURL *)fileUrl { - (void)addFileIfMissing:(NSURL *)fileUrl {
@ -263,10 +263,10 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
NSURL *url = [SandboxBroker urlWithoutFragment:fileUrl]; NSURL *url = [SandboxBroker urlWithoutFragment:fileUrl];
@synchronized (self) { dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
SandboxEntry *_entry = nil; SandboxEntry *_entry = nil;
for(SandboxEntry *entry in storage) { for(SandboxEntry *entry in self->storage) {
if(entry.path) { if(entry.path) {
if((entry.isFolder && [SandboxBroker isPath:url aSubdirectoryOf:[NSURL fileURLWithPath:entry.path]]) || if((entry.isFolder && [SandboxBroker isPath:url aSubdirectoryOf:[NSURL fileURLWithPath:entry.path]]) ||
(!entry.isFolder && [url isEqualTo:[NSURL fileURLWithPath:entry.path]])) { (!entry.isFolder && [url isEqualTo:[NSURL fileURLWithPath:entry.path]])) {
@ -300,17 +300,17 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
} }
}]; }];
} }
} });
} }
- (void)requestFolderForFile:(NSURL *)fileUrl { - (void)requestFolderForFile:(NSURL *)fileUrl {
if(![fileUrl isFileURL]) return; if(![fileUrl isFileURL]) return;
NSURL *folderUrl = [fileUrl URLByDeletingLastPathComponent]; NSURL *folderUrl = [fileUrl URLByDeletingLastPathComponent];
@synchronized(self) { dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
SandboxEntry *_entry = nil; SandboxEntry *_entry = nil;
for(SandboxEntry *entry in storage) { for(SandboxEntry *entry in self->storage) {
if(entry.path && entry.isFolder && [SandboxBroker isPath:folderUrl aSubdirectoryOf:[NSURL fileURLWithPath:entry.path]]) { if(entry.path && entry.isFolder && [SandboxBroker isPath:folderUrl aSubdirectoryOf:[NSURL fileURLWithPath:entry.path]]) {
_entry = entry; _entry = entry;
break; break;
@ -366,7 +366,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
} }
}); });
} }
} });
} }
+ (void)cleanupFolderAccess { + (void)cleanupFolderAccess {
@ -417,12 +417,12 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
NSURL *folderUrl = [SandboxBroker urlWithoutFragment:fileUrl]; NSURL *folderUrl = [SandboxBroker urlWithoutFragment:fileUrl];
if(![folderUrl isFileURL]) return NULL; if(![folderUrl isFileURL]) return NULL;
SandboxEntry *_entry = nil; __block SandboxEntry *_entry = nil;
NSString *sandboxPath = [folderUrl path]; NSString *sandboxPath = [folderUrl path];
@synchronized(self) { dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
for(SandboxEntry *entry in storage) { for(SandboxEntry *entry in self->storage) {
if(entry.path) { if(entry.path) {
if((entry.isFolder && [SandboxBroker isPath:folderUrl aSubdirectoryOf:[NSURL fileURLWithPath:entry.path]]) || if((entry.isFolder && [SandboxBroker isPath:folderUrl aSubdirectoryOf:[NSURL fileURLWithPath:entry.path]]) ||
(!entry.isFolder && [entry.path isEqualToString:sandboxPath])) { (!entry.isFolder && [entry.path isEqualToString:sandboxPath])) {
@ -438,17 +438,20 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
} }
if(_entry) { if(_entry) {
[storage addObject:_entry]; [self->storage addObject:_entry];
if(_entry.secureUrl) { if(_entry.secureUrl) {
[_entry.secureUrl startAccessingSecurityScopedResource]; [_entry.secureUrl startAccessingSecurityScopedResource];
} }
return CFBridgingRetain(_entry);
} else { } else {
return NULL; _entry = NULL;
} }
} });
if(_entry)
return CFBridgingRetain(_entry);
else
return NULL;
} }
- (void)endFolderAccess:(const void *)handle { - (void)endFolderAccess:(const void *)handle {