Skip to content

Commit 14eefef

Browse files
committed
Fix crash in dispatch queue assertion with background tasks
1 parent dfa2979 commit 14eefef

File tree

7 files changed

+43
-79
lines changed

7 files changed

+43
-79
lines changed

ios/MullvadVPN/AddressCacheTracker/AddressCacheTracker.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ final class AddressCacheTracker: @unchecked Sendable {
8484
timer = nil
8585
}
8686

87-
func updateEndpoints(completionHandler: (@Sendable (Result<Bool, Error>) -> Void)? = nil) -> Cancellable {
87+
func updateEndpoints(completionHandler: ((sending Result<Bool, Error>) -> Void)? = nil) -> Cancellable {
8888
let operation = ResultBlockOperation<Bool> { finish -> Cancellable in
8989
guard self.nextScheduleDate() <= Date() else {
9090
finish(.success(false))

ios/MullvadVPN/AppDelegate.swift

+11-20
Original file line numberDiff line numberDiff line change
@@ -277,15 +277,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
277277
private func registerAppRefreshTask() {
278278
let isRegistered = BGTaskScheduler.shared.register(
279279
forTaskWithIdentifier: BackgroundTask.appRefresh.identifier,
280-
using: nil
280+
using: .main
281281
) { [self] task in
282-
nonisolated(unsafe) let nonisolatedTask = task
283282

284283
let handle = relayCacheTracker.updateRelays { result in
285-
nonisolatedTask.setTaskCompleted(success: result.isSuccess)
284+
task.setTaskCompleted(success: result.isSuccess)
286285
}
287286

288-
nonisolatedTask.expirationHandler = {
287+
task.expirationHandler = {
289288
handle.cancel()
290289
}
291290

@@ -302,18 +301,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
302301
private func registerKeyRotationTask() {
303302
let isRegistered = BGTaskScheduler.shared.register(
304303
forTaskWithIdentifier: BackgroundTask.privateKeyRotation.identifier,
305-
using: nil
304+
using: .main
306305
) { [self] task in
307-
nonisolated(unsafe) let nonisolatedTask = task
308306
let handle = tunnelManager.rotatePrivateKey { [self] error in
309-
Task { @MainActor in
310-
scheduleKeyRotationTask()
311-
312-
nonisolatedTask.setTaskCompleted(success: error == nil)
313-
}
307+
scheduleKeyRotationTask()
308+
task.setTaskCompleted(success: error == nil)
314309
}
315310

316-
nonisolatedTask.expirationHandler = {
311+
task.expirationHandler = {
317312
handle.cancel()
318313
}
319314
}
@@ -328,18 +323,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
328323
private func registerAddressCacheUpdateTask() {
329324
let isRegistered = BGTaskScheduler.shared.register(
330325
forTaskWithIdentifier: BackgroundTask.addressCacheUpdate.identifier,
331-
using: nil
326+
using: .main
332327
) { [self] task in
333-
nonisolated(unsafe) let nonisolatedTask = task
334-
335328
let handle = addressCacheTracker.updateEndpoints { [self] result in
336-
Task { @MainActor in
337-
scheduleAddressCacheUpdateTask()
338-
nonisolatedTask.setTaskCompleted(success: result.isSuccess)
339-
}
329+
scheduleAddressCacheUpdateTask()
330+
task.setTaskCompleted(success: result.isSuccess)
340331
}
341332

342-
nonisolatedTask.expirationHandler = {
333+
task.expirationHandler = {
343334
handle.cancel()
344335
}
345336
}

ios/MullvadVPN/RelayCacheTracker/RelayCacheTracker.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import UIKit
1616
protocol RelayCacheTrackerProtocol: Sendable {
1717
func startPeriodicUpdates()
1818
func stopPeriodicUpdates()
19-
func updateRelays(completionHandler: (@Sendable (Result<RelaysFetchResult, Error>) -> Void)?) -> Cancellable
19+
func updateRelays(completionHandler: ((sending Result<RelaysFetchResult, Error>) -> Void)?) -> Cancellable
2020
func getCachedRelays() throws -> CachedRelays
2121
func getNextUpdateDate() -> Date
2222
func addObserver(_ observer: RelayCacheTrackerObserver)
@@ -164,7 +164,7 @@ final class RelayCacheTracker: RelayCacheTrackerProtocol, @unchecked Sendable {
164164
timerSource = nil
165165
}
166166

167-
func updateRelays(completionHandler: (@Sendable (Result<RelaysFetchResult, Error>) -> Void)? = nil)
167+
func updateRelays(completionHandler: ((sending Result<RelaysFetchResult, Error>) -> Void)? = nil)
168168
-> Cancellable {
169169
let operation = ResultBlockOperation<RelaysFetchResult> { finish in
170170
let cachedRelays = try? self.getCachedRelays()

ios/MullvadVPN/TunnelManager/BackgroundTaskProvider.swift

+3-21
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,10 @@ import UIKit
1414
@available(iOSApplicationExtension, unavailable)
1515
public protocol BackgroundTaskProviding: Sendable {
1616
var backgroundTimeRemaining: TimeInterval { get }
17-
#if compiler(>=6)
18-
nonisolated
19-
func beginBackgroundTask(
17+
nonisolated func beginBackgroundTask(
2018
withName taskName: String?,
2119
expirationHandler handler: (@MainActor @Sendable () -> Void)?
2220
) -> UIBackgroundTaskIdentifier
23-
#else
24-
func beginBackgroundTask(
25-
withName taskName: String?,
26-
expirationHandler handler: (() -> Void)?
27-
) -> UIBackgroundTaskIdentifier
28-
#endif
2921

3022
func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier)
3123
}
@@ -40,22 +32,12 @@ public final class BackgroundTaskProvider: BackgroundTaskProviding {
4032
self.application = application
4133
}
4234

43-
#if compiler(>=6)
44-
nonisolated
45-
public func beginBackgroundTask(
46-
withName taskName: String?,
47-
expirationHandler handler: (@MainActor @Sendable () -> Void)?
48-
) -> UIBackgroundTaskIdentifier {
49-
application.beginBackgroundTask(withName: taskName, expirationHandler: handler)
50-
}
51-
#else
52-
public func beginBackgroundTask(
35+
nonisolated public func beginBackgroundTask(
5336
withName taskName: String?,
54-
expirationHandler handler: (() -> Void)?
37+
expirationHandler handler: (@MainActor @Sendable () -> Void)? = nil
5538
) -> UIBackgroundTaskIdentifier {
5639
application.beginBackgroundTask(withName: taskName, expirationHandler: handler)
5740
}
58-
#endif
5941

6042
public func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier) {
6143
application.endBackgroundTask(identifier)

ios/MullvadVPN/TunnelManager/TunnelManager.swift

+23-32
Original file line numberDiff line numberDiff line change
@@ -218,29 +218,25 @@ final class TunnelManager: StorePaymentObserver, @unchecked Sendable {
218218
}
219219

220220
func startTunnel(completionHandler: ((Error?) -> Void)? = nil) {
221-
nonisolated(unsafe) let nonisolatedCompletionHandler = completionHandler
222-
223221
let operation = StartTunnelOperation(
224222
dispatchQueue: internalQueue,
225223
interactor: TunnelInteractorProxy(self),
226224
completionHandler: { [weak self] result in
227225
guard let self else { return }
228-
DispatchQueue.main.async {
229-
if let error = result.error {
230-
self.logger.error(
231-
error: error,
232-
message: "Failed to start the tunnel."
233-
)
234-
235-
let tunnelError = StartTunnelError(underlyingError: error)
236-
237-
self.observerList.notify { observer in
238-
observer.tunnelManager(self, didFailWithError: tunnelError)
239-
}
240-
}
226+
if let error = result.error {
227+
self.logger.error(
228+
error: error,
229+
message: "Failed to start the tunnel."
230+
)
231+
232+
let tunnelError = StartTunnelError(underlyingError: error)
241233

242-
nonisolatedCompletionHandler?(result.error)
234+
self.observerList.notify { observer in
235+
observer.tunnelManager(self, didFailWithError: tunnelError)
236+
}
243237
}
238+
239+
completionHandler?(result.error)
244240
}
245241
)
246242

@@ -255,29 +251,26 @@ final class TunnelManager: StorePaymentObserver, @unchecked Sendable {
255251
}
256252

257253
func stopTunnel(completionHandler: ((Error?) -> Void)? = nil) {
258-
nonisolated(unsafe) let nonisolatedCompletionHandler = completionHandler
259254
let operation = StopTunnelOperation(
260255
dispatchQueue: internalQueue,
261256
interactor: TunnelInteractorProxy(self)
262257
) { [weak self] result in
263258
guard let self else { return }
264259

265-
DispatchQueue.main.async {
266-
if let error = result.error {
267-
self.logger.error(
268-
error: error,
269-
message: "Failed to stop the tunnel."
270-
)
260+
if let error = result.error {
261+
self.logger.error(
262+
error: error,
263+
message: "Failed to stop the tunnel."
264+
)
271265

272-
let tunnelError = StopTunnelError(underlyingError: error)
266+
let tunnelError = StopTunnelError(underlyingError: error)
273267

274-
self.observerList.notify { observer in
275-
observer.tunnelManager(self, didFailWithError: tunnelError)
276-
}
268+
self.observerList.notify { observer in
269+
observer.tunnelManager(self, didFailWithError: tunnelError)
277270
}
278-
279-
nonisolatedCompletionHandler?(result.error)
280271
}
272+
273+
completionHandler?(result.error)
281274
}
282275

283276
operation.addObserver(BackgroundObserver(
@@ -482,7 +475,7 @@ final class TunnelManager: StorePaymentObserver, @unchecked Sendable {
482475
operationQueue.addOperation(operation)
483476
}
484477

485-
func rotatePrivateKey(completionHandler: @escaping @Sendable (Error?) -> Void) -> Cancellable {
478+
func rotatePrivateKey(completionHandler: @MainActor @escaping @Sendable (Error?) -> Void) -> Cancellable {
486479
let operation = RotateKeyOperation(
487480
dispatchQueue: internalQueue,
488481
interactor: TunnelInteractorProxy(self),
@@ -499,8 +492,6 @@ final class TunnelManager: StorePaymentObserver, @unchecked Sendable {
499492
if let error {
500493
handleRestError(error)
501494
}
502-
503-
completionHandler(error)
504495
}
505496

506497
operation.addObserver(

ios/MullvadVPNTests/MullvadVPN/RelayCacheTracker/RelayCacheTracker+Stubs.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct RelayCacheTrackerStub: RelayCacheTrackerProtocol {
1515

1616
func stopPeriodicUpdates() {}
1717

18-
func updateRelays(completionHandler: ((Result<RelaysFetchResult, Error>) -> Void)?) -> Cancellable {
18+
func updateRelays(completionHandler: sending ((Result<RelaysFetchResult, Error>) -> Void)?) -> Cancellable {
1919
AnyCancellable()
2020
}
2121

ios/Operations/ResultOperation.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010

1111
/// Base class for operations producing result.
1212
open class ResultOperation<Success: Sendable>: AsyncOperation, OutputOperation, @unchecked Sendable {
13-
public typealias CompletionHandler = @Sendable (Result<Success, Error>) -> Void
13+
public typealias CompletionHandler = (sending Result<Success, Error>) -> Void
1414

1515
private let nslock = NSLock()
1616
private var _output: Success?
@@ -118,7 +118,7 @@ open class ResultOperation<Success: Sendable>: AsyncOperation, OutputOperation,
118118
let completionQueue = _completionQueue
119119
nslock.unlock()
120120

121-
let block: @Sendable () -> Void = {
121+
let block: () -> Void = {
122122
// Call completion handler.
123123
completionHandler?(result)
124124

0 commit comments

Comments
 (0)