Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: add serial dispatch queue for storedCalls to avoid data-race #7480

Merged
merged 6 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ios/Capacitor/Capacitor/CapacitorBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
// Manager for getting Cordova plugins
var cordovaPluginManager: CDVPluginManager?
// Calls we are storing to resolve later
var storedCalls = [String: CAPPluginCall]()
var storedCalls = ConcurrentDictionary<CAPPluginCall>()
// Whether to inject the Cordova files
private var injectCordovaFiles = false
private var cordovaParser: CDVConfigParser?
Expand Down Expand Up @@ -276,7 +276,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
sending data back to the page from a previous page.
*/
func reset() {
storedCalls = [String: CAPPluginCall]()
storedCalls.withLock { $0.removeAll() }
}

/**
Expand Down Expand Up @@ -386,7 +386,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
}

@objc public func releaseCall(withID: String) {
storedCalls.removeValue(forKey: withID)
let _ = storedCalls.withLock { $0.removeValue(forKey: withID) }
}

// MARK: - Deprecated Versions
Expand Down
13 changes: 10 additions & 3 deletions ios/Capacitor/Capacitor/KeyValueStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,12 @@ private class InMemoryStore: KeyValueStoreBackend {
}
}

private class ConcurrentDictionary<Value> {
private var storage: [String: Value]
class ConcurrentDictionary<Value> {
typealias StorageType = [String: Value]
private var storage: StorageType
private let lock = NSLock()

init(_ initial: [String: Value] = [:]) {
init(_ initial: StorageType = [:]) {
storage = initial
}

Expand All @@ -293,4 +294,10 @@ private class ConcurrentDictionary<Value> {
}
}
}

func withLock<T>(_ body: (_ storage: inout StorageType) -> T) -> T {
lock.withLock {
body(&storage)
}
}
}