Files
ios-mail/Modules/App/Sources/Utils/Timer/TimerFactory.swift
T
Maciej Gomółka 0c245faf99 Introduce wait for active session before finishing background task
When the app is updated while in the background, the system
cold-launches your process and immediately fires your background task.
Because your initialization (mail user session setup) isn't yet
complete, the background task's work ends too soon and the system
thinks you've finished all background activity.

That violates the expectation that no further background work should
occur once the task reports completion.

Scenario
1. App is installed and user is logged in.
2. User goes background.
3. App is updated.
4. System cold-runs the updated app to execute scheduled background
   tasks.
5. Background task starts together with session initialization.

Background task finsihes first and we let the system know that all
background execution is completed - which is not true and usually
cause crash, in our case `0xdead10cc` - deadlock. The reason is we
didn't have enough of time to release file locks.
2025-04-25 11:24:20 +02:00

30 lines
1.0 KiB
Swift

// Copyright (c) 2025 Proton Technologies AG
//
// This file is part of Proton Mail.
//
// Proton Mail is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import Combine
import Foundation
enum TimerFactory {
static func make(timeInterval: TimeInterval) -> AnyPublisher<Void, Never> {
Timer.TimerPublisher(interval: timeInterval, runLoop: .main, mode: .default)
.autoconnect()
.map { _ in }
.prepend(())
.eraseToAnyPublisher()
}
}