Skip to content

Commit

Permalink
Avoid deadlocking the Packet Tunnel after a reboot
Browse files Browse the repository at this point in the history
  • Loading branch information
buggmagnet committed Oct 30, 2024
1 parent ee37deb commit d42c0ab
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 20 deletions.
3 changes: 3 additions & 0 deletions ios/MullvadSettings/MigrationManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ public struct MigrationManager {
)
} catch .itemNotFound as KeychainError {
migrationCompleted(.nothing)
} catch let couldNotReadKeychainError as KeychainError
where couldNotReadKeychainError == .interactionNotAllowed {
migrationCompleted(.failure(couldNotReadKeychainError))
} catch {
resetStoreHandler(.failure(error))
}
Expand Down
48 changes: 28 additions & 20 deletions ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -174,28 +174,36 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
}

private func performSettingsMigration() {
migrationManager.migrateSettings(
store: SettingsManager.store,
migrationCompleted: { [unowned self] migrationResult in
switch migrationResult {
case .success:
providerLogger.debug("Successful migration from PacketTunnel")
case .nothing:
providerLogger.debug("Attempted migration from PacketTunnel, but found nothing to do")
case let .failure(error):
// `next` returns an Optional value, but this iterator is guaranteed to always have a next value
guard let delay = migrationFailureIterator.next() else { return }
providerLogger
.error(
"Failed migration from PacketTunnel: \(error), retrying in \(delay.timeInterval) seconds"
)
// Block the launch of the Packet Tunnel for as long as the settings migration fail.
// The process watchdog introduced by iOS 17 will kill this process after 60 seconds.
Thread.sleep(forTimeInterval: delay.timeInterval)
performSettingsMigration()
var hasNotMigrated = true
repeat {
migrationManager.migrateSettings(
store: SettingsManager.store,
migrationCompleted: { [unowned self] migrationResult in
switch migrationResult {
case .success:
providerLogger.debug("Successful migration from PacketTunnel")
hasNotMigrated = false
case .nothing:
hasNotMigrated = false
providerLogger.debug("Attempted migration from PacketTunnel, but found nothing to do")
case let .failure(error):
providerLogger
.error(
"Failed migration from PacketTunnel: \(error)"
)
}
}
)
if hasNotMigrated {
// `next` returns an Optional value, but this iterator is guaranteed to always have a next value
guard let delay = migrationFailureIterator.next() else { continue }

providerLogger.error("Retrying migration in \(delay.timeInterval) seconds")
// Block the launch of the Packet Tunnel for as long as the settings migration fail.
// The process watchdog introduced by iOS 17 will kill this process after 60 seconds.
Thread.sleep(forTimeInterval: delay.timeInterval)
}
)
} while hasNotMigrated
}

private func setUpTransportProvider(
Expand Down

0 comments on commit d42c0ab

Please sign in to comment.