Prechádzať zdrojové kódy

hotfix: appIsInForeground() must not be called from non-main thread (#1551)

bjoern 3 rokov pred
rodič
commit
51233044e4
1 zmenil súbory, kde vykonal 22 pridanie a 18 odobranie
  1. 22 18
      deltachat-ios/AppDelegate.swift

+ 22 - 18
deltachat-ios/AppDelegate.swift

@@ -455,10 +455,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         // move work to non-main thread to not block UI (otherwise, in case we get suspended, the app is blocked totally)
         // (we are using `qos: default` as `qos: .background` or `main.asyncAfter` may be delayed by tens of minutes)
         DispatchQueue.global().async { [weak self] in
-            guard let self = self else {
-                completionHandler(.failed)
-                return
-            }
+            guard let self = self else { completionHandler(.failed); return }
 
             // we're in background, run IO for a little time
             self.dcAccounts.startIo()
@@ -473,22 +470,29 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             // cmp. https://github.com/deltachat/deltachat-ios/pull/1542#pullrequestreview-951620906
             logger.info("⬅️ finishing fetch")
 
-            if !self.appIsInForeground() {
-                self.dcAccounts.stopIo()
-            }
-
-            // to avoid 0xdead10cc exceptions, scheduled jobs need to be done before we get suspended;
-            // we increase the probabilty that this happens by waiting a moment before calling completionHandler()
-            _ = fetchSemaphore.wait(timeout: .now() + 1)
+            // dispatch back to main as we cannot check the foreground state from non-main thread
+            // (this again has the risk to be delayed by tens of minutes, however, fetch is done and we're mostly fine)
+            DispatchQueue.main.async { [weak self] in
+                guard let self = self else { completionHandler(.failed); return }
 
-            logger.info("⬅️ fetch done")
-
-            self.pushToDebugArray(name: "notify-fetch-durations", value: Double(Date().timeIntervalSince1970)-nowTimestamp)
-            completionHandler(.newData)
+                if !self.appIsInForeground() {
+                    self.dcAccounts.stopIo()
+                }
 
-            if backgroundTask != .invalid {
-                UIApplication.shared.endBackgroundTask(backgroundTask)
-                backgroundTask = .invalid
+                // to avoid 0xdead10cc exceptions, scheduled jobs need to be done before we get suspended;
+                // we increase the probabilty that this happens by waiting a moment before calling completionHandler()
+                DispatchQueue.global().async { [weak self] in
+                    guard let self = self else { completionHandler(.failed); return }
+
+                    _ = fetchSemaphore.wait(timeout: .now() + 1)
+                    logger.info("⬅️ fetch done")
+                    self.pushToDebugArray(name: "notify-fetch-durations", value: Double(Date().timeIntervalSince1970)-nowTimestamp)
+                    completionHandler(.newData)
+                    if backgroundTask != .invalid {
+                        UIApplication.shared.endBackgroundTask(backgroundTask)
+                        backgroundTask = .invalid
+                    }
+                }
             }
         }
     }