Skip to content

Commit 6829313

Browse files
committed
Avoid deadlocking the Packet Tunnel after a reboot
1 parent ddfb746 commit 6829313

File tree

2 files changed

+31
-20
lines changed

2 files changed

+31
-20
lines changed

ios/MullvadSettings/MigrationManager.swift

+3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ public struct MigrationManager {
6868
)
6969
} catch .itemNotFound as KeychainError {
7070
migrationCompleted(.nothing)
71+
} catch let couldNotReadKeychainError as KeychainError
72+
where couldNotReadKeychainError == .interactionNotAllowed {
73+
migrationCompleted(.failure(couldNotReadKeychainError))
7174
} catch {
7275
resetStoreHandler(.failure(error))
7376
}

ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift

+28-20
Original file line numberDiff line numberDiff line change
@@ -174,28 +174,36 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
174174
}
175175

176176
private func performSettingsMigration() {
177-
migrationManager.migrateSettings(
178-
store: SettingsManager.store,
179-
migrationCompleted: { [unowned self] migrationResult in
180-
switch migrationResult {
181-
case .success:
182-
providerLogger.debug("Successful migration from PacketTunnel")
183-
case .nothing:
184-
providerLogger.debug("Attempted migration from PacketTunnel, but found nothing to do")
185-
case let .failure(error):
186-
// `next` returns an Optional value, but this iterator is guaranteed to always have a next value
187-
guard let delay = migrationFailureIterator.next() else { return }
188-
providerLogger
189-
.error(
190-
"Failed migration from PacketTunnel: \(error), retrying in \(delay.timeInterval) seconds"
191-
)
192-
// Block the launch of the Packet Tunnel for as long as the settings migration fail.
193-
// The process watchdog introduced by iOS 17 will kill this process after 60 seconds.
194-
Thread.sleep(forTimeInterval: delay.timeInterval)
195-
performSettingsMigration()
177+
var hasNotMigrated = true
178+
repeat {
179+
migrationManager.migrateSettings(
180+
store: SettingsManager.store,
181+
migrationCompleted: { [unowned self] migrationResult in
182+
switch migrationResult {
183+
case .success:
184+
providerLogger.debug("Successful migration from PacketTunnel")
185+
hasNotMigrated = false
186+
case .nothing:
187+
hasNotMigrated = false
188+
providerLogger.debug("Attempted migration from PacketTunnel, but found nothing to do")
189+
case let .failure(error):
190+
providerLogger
191+
.error(
192+
"Failed migration from PacketTunnel: \(error)"
193+
)
194+
}
196195
}
196+
)
197+
if hasNotMigrated {
198+
// `next` returns an Optional value, but this iterator is guaranteed to always have a next value
199+
guard let delay = migrationFailureIterator.next() else { continue }
200+
201+
providerLogger.error("Retrying migration in \(delay.timeInterval) seconds")
202+
// Block the launch of the Packet Tunnel for as long as the settings migration fail.
203+
// The process watchdog introduced by iOS 17 will kill this process after 60 seconds.
204+
Thread.sleep(forTimeInterval: delay.timeInterval)
197205
}
198-
)
206+
} while hasNotMigrated
199207
}
200208

201209
private func setUpTransportProvider(

0 commit comments

Comments
 (0)