fix: on some machines, deadlocks happened at launch
This commit is contained in:
1 parent
126eca5c35
commit
e2181c8756
2 files changed
+11
-9
No files matched your search
@@ -10,8 +10,6 @@ class BackgroundWork {
|
||||
|
||||
// we cap concurrent tasks to .processorCount to avoid thread explosion on the .global queue
|
||||
static let globalSemaphore = DispatchSemaphore(value: ProcessInfo.processInfo.processorCount)
|
||||
// AX calls may block for a long time. We use a big semaphore to avoid blocking the main thread in case the window server is busy
|
||||
static let axCallsGlobalSemaphore = DispatchSemaphore(value: 100)
|
||||
|
||||
// swift static variables are lazy; we artificially force the threads to init
|
||||
static func start() {
|
||||
@@ -25,12 +23,12 @@ extension DispatchQueue {
|
||||
return DispatchQueue(label: label, target: .global(qos: qos.qosClass))
|
||||
}
|
||||
|
||||
func asyncWithCap(_ deadline: DispatchTime? = nil, semaphore: DispatchSemaphore = BackgroundWork.globalSemaphore, _ fn: @escaping () -> Void) {
|
||||
func asyncWithCap(_ deadline: DispatchTime? = nil, _ fn: @escaping () -> Void) {
|
||||
let block = {
|
||||
fn()
|
||||
semaphore.signal()
|
||||
BackgroundWork.globalSemaphore.signal()
|
||||
}
|
||||
semaphore.wait()
|
||||
BackgroundWork.globalSemaphore.wait()
|
||||
if let deadline = deadline {
|
||||
asyncAfter(deadline: deadline, execute: block)
|
||||
} else {
|
||||
|
||||
@@ -7,15 +7,19 @@ func axObserverCallback(observer: AXObserver, element: AXUIElement, notification
|
||||
|
||||
// if the window server is busy, it may not reply to AX calls. We retry right before the call times-out and returns a bogus value
|
||||
func retryAxCallUntilTimeout(_ fn: @escaping () throws -> Void, _ startTime: DispatchTime = DispatchTime.now()) {
|
||||
BackgroundWork.axCallsQueue.asyncWithCap(semaphore: BackgroundWork.axCallsGlobalSemaphore) {
|
||||
BackgroundWork.axCallsQueue.async {
|
||||
retryAxCallUntilTimeout_(fn, startTime)
|
||||
}
|
||||
}
|
||||
|
||||
func retryAxCallUntilTimeout_(_ fn: @escaping () throws -> Void, _ startTime: DispatchTime = DispatchTime.now()) {
|
||||
do {
|
||||
try fn()
|
||||
} catch {
|
||||
let timePassedInSeconds = Double(DispatchTime.now().uptimeNanoseconds - startTime.uptimeNanoseconds) / 1_000_000_000
|
||||
if timePassedInSeconds < Double(AXUIElement.globalTimeoutInSeconds) {
|
||||
BackgroundWork.axCallsQueue.asyncWithCap(.now() + .milliseconds(10), semaphore: BackgroundWork.axCallsGlobalSemaphore) {
|
||||
retryAxCallUntilTimeout(fn, startTime)
|
||||
}
|
||||
BackgroundWork.axCallsQueue.asyncAfter(deadline: .now() + .milliseconds(10)) {
|
||||
retryAxCallUntilTimeout_(fn, startTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user