Răsfoiți Sursa

Lock publick methods to prevent concurrency issues

Evgenii Neumerzhitckii 6 ani în urmă
părinte
comite
b308990d95
1 a modificat fișierele cu 34 adăugiri și 5 ștergeri
  1. 34 5
      Distrib/KeychainSwiftDistrib.swift

+ 34 - 5
Distrib/KeychainSwiftDistrib.swift

@@ -48,7 +48,8 @@ open class KeychainSwift {
   */
   open var synchronizable: Bool = false
 
-  private let readLock = NSLock()
+  private let lock = NSLock()
+
   
   /// Instantiate a KeychainSwift object
   public init() { }
@@ -99,7 +100,12 @@ open class KeychainSwift {
   open func set(_ value: Data, forKey key: String,
     withAccess access: KeychainSwiftAccessOptions? = nil) -> Bool {
     
-    delete(key) // Delete any existing key before saving it
+    // The lock prevents the code to be run simlultaneously
+    // from multiple threads which may result in crashing
+    lock.lock()
+    defer { lock.unlock() }
+    
+    deleteNoLock(key) // Delete any existing key before saving it
 
     let accessible = access?.value ?? KeychainSwiftAccessOptions.defaultOption.value
       
@@ -175,8 +181,8 @@ open class KeychainSwift {
   open func getData(_ key: String, asReference: Bool = false) -> Data? {
     // The lock prevents the code to be run simlultaneously
     // from multiple threads which may result in crashing
-    readLock.lock()
-    defer { readLock.unlock() }
+    lock.lock()
+    defer { lock.unlock() }
     
     let prefixedKey = keyWithPrefix(key)
     
@@ -233,8 +239,26 @@ open class KeychainSwift {
   */
   @discardableResult
   open func delete(_ key: String) -> Bool {
+    // The lock prevents the code to be run simlultaneously
+    // from multiple threads which may result in crashing
+    lock.lock()
+    defer { lock.unlock() }
+    
+    return deleteNoLock(key)
+  }
+  
+  /**
+   
+  Same as `delete` but is only accessed internally, since it is not thread safe.
+   
+   - parameter key: The key that is used to delete the keychain item.
+   - returns: True if the item was successfully deleted.
+   
+   */
+  @discardableResult
+  func deleteNoLock(_ key: String) -> Bool {
     let prefixedKey = keyWithPrefix(key)
-
+    
     var query: [String: Any] = [
       KeychainSwiftConstants.klass       : kSecClassGenericPassword,
       KeychainSwiftConstants.attrAccount : prefixedKey
@@ -258,6 +282,11 @@ open class KeychainSwift {
   */
   @discardableResult
   open func clear() -> Bool {
+    // The lock prevents the code to be run simlultaneously
+    // from multiple threads which may result in crashing
+    lock.lock()
+    defer { lock.unlock() }
+    
     var query: [String: Any] = [ kSecClass as String : kSecClassGenericPassword ]
     query = addAccessGroupWhenPresent(query)
     query = addSynchronizableIfRequired(query, addingItems: false)