Skip to content

Commit aee55a2

Browse files
anfuereranfuererrobingenz
authored
fix(background-task): ensure thread-safety on iOS (#779)
* fix(background-task): ensure thread-safety of the taskIds dictionary * fix(background-task): ensure thread-safety of the taskIds dictionary * Update .changeset/wet-clubs-begin.md --------- Co-authored-by: anfuerer <admail@gmx.ch> Co-authored-by: Robin Genz <mail@robingenz.dev>
1 parent 6b9cdf6 commit aee55a2

File tree

2 files changed

+19
-7
lines changed

2 files changed

+19
-7
lines changed

.changeset/wet-clubs-begin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@capawesome/capacitor-background-task': patch
3+
---
4+
5+
fix(ios): ensure thread-safety

packages/background-task/ios/Plugin/BackgroundTask.swift

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,30 @@ import Foundation
22
import UIKit
33

44
@objc public class BackgroundTask: NSObject {
5-
var taskIds: [String: UIBackgroundTaskIdentifier] = [:]
5+
private let isolationQueue = DispatchQueue(label: "io.capawesome.backgroundtask.isolation")
6+
private var taskIds: [String: UIBackgroundTaskIdentifier] = [:]
67

78
@objc public func beforeExit(_ callbackId: String) {
8-
DispatchQueue.global().async {
9+
// Use the isolation queue to synchronize access to the taskIds dictionary
10+
isolationQueue.async { [weak self] in
11+
guard let self = self else { return }
12+
913
var taskId = UIBackgroundTaskIdentifier.invalid
1014
taskId = UIApplication.shared.beginBackgroundTask {
11-
// Finish the task if time expires.
12-
UIApplication.shared.endBackgroundTask(taskId)
13-
self.taskIds.removeValue(forKey: callbackId)
15+
// Finish the task if time expires. This expiration handler can run on any thread,
16+
// so we MUST hop back to the isolation queue.
17+
self.isolationQueue.async {
18+
UIApplication.shared.endBackgroundTask(taskId)
19+
self.taskIds.removeValue(forKey: callbackId)
20+
}
1421
}
1522
self.taskIds[callbackId] = taskId
1623
}
1724
}
1825

1926
@objc public func finish(_ callbackId: String) {
20-
DispatchQueue.global().async {
21-
guard let taskId = self.taskIds[callbackId] else {
27+
isolationQueue.async { [weak self] in
28+
guard let self = self, let taskId = self.taskIds[callbackId] else {
2229
return
2330
}
2431
UIApplication.shared.endBackgroundTask(taskId)

0 commit comments

Comments
 (0)