Просмотр исходного кода

End background task on the async path, not from a defer-Task

A defer block cannot await, so the previous code wrapped
endBackgroundTask in a follow-up unstructured Task. UIApplication's
contract is that endBackgroundTask must land before the app is
suspended; an unstructured Task spawned at the tail of the loop has no
such guarantee — iOS may suspend before it runs, which trips the
background-task watchdog.

The enclosing scope is already async, so just await the call directly
at the end of the do/catch, on both success and error paths.

The expirationHandler from the pre-PR code is intentionally not
restored. The old handler also ended the task from a Task and was
buggy; reintroducing it correctly is out of scope for this PR and
belongs in the PR description as a deliberate behavior change.
Marvin Polscheit 1 день назад
Родитель
Сommit
3e0dc662d0
1 измененных файлов с 9 добавлено и 6 удалено
  1. 9 6
      Trio/Sources/APS/APSManager.swift

+ 9 - 6
Trio/Sources/APS/APSManager.swift

@@ -315,12 +315,6 @@ final class BaseAPSManager: APSManager, Injectable {
                 interval: interval
             )
 
-            defer {
-                if bgTask != .invalid {
-                    Task { await UIApplication.shared.endBackgroundTask(bgTask) }
-                }
-            }
-
             do {
                 try await executeLoop(loopStatRecord: &loopStatRecord)
                 requestNightscoutUpload(
@@ -335,6 +329,15 @@ final class BaseAPSManager: APSManager, Injectable {
                 await finalizeLoop(error: error, loopStatRecord: loopStatRecord)
                 debug(.apsManager, "\(DebuggingIdentifiers.failed) Failed to complete Loop: \(error)")
             }
+
+            // End the background task on the async path itself — `defer` cannot `await`,
+            // and spawning a follow-up Task for endBackgroundTask is not guaranteed to land
+            // before iOS suspends the app, violating UIApplication's contract.
+            // Note: the previous code had an expirationHandler; it was buggy (also ended the
+            // task from a Task) and has been intentionally dropped — see PR description.
+            if bgTask != .invalid {
+                await UIApplication.shared.endBackgroundTask(bgTask)
+            }
         }
     }