From 7258a8da2e32704c156c11ef611cc7961d085681 Mon Sep 17 00:00:00 2001 From: Alexander Smarus Date: Mon, 25 Dec 2023 14:39:24 +0200 Subject: [PATCH] Make _MultiHandle timeout timer non-repeatable CURL documentation (https://curl.se/libcurl/c/CURLMOPT_TIMERFUNCTION.html) explicitly says that the timer should be one-time. We basically have to follow CURL requests for setting, resetting and disarming such timers. Current logic eventually leaves a 1ms repeating timer forever, because CURL assumes it fires once, and may not ask us to remove it explicitly. Also, being used as request timeout trigger, this timer also has no sense to be repeated. --- .../URLSession/libcurl/MultiHandle.swift | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Sources/FoundationNetworking/URLSession/libcurl/MultiHandle.swift b/Sources/FoundationNetworking/URLSession/libcurl/MultiHandle.swift index 19bda9723d..6196b2fa39 100644 --- a/Sources/FoundationNetworking/URLSession/libcurl/MultiHandle.swift +++ b/Sources/FoundationNetworking/URLSession/libcurl/MultiHandle.swift @@ -359,7 +359,7 @@ class _TimeoutSource { let delay = UInt64(max(1, milliseconds - 1)) let start = DispatchTime.now() + DispatchTimeInterval.milliseconds(Int(delay)) - rawSource.schedule(deadline: start, repeating: .milliseconds(Int(delay)), leeway: (milliseconds == 1) ? .microseconds(Int(1)) : .milliseconds(Int(1))) + rawSource.schedule(deadline: start, repeating: .never, leeway: (milliseconds == 1) ? .microseconds(Int(1)) : .milliseconds(Int(1))) rawSource.setEventHandler(handler: handler) rawSource.resume() } @@ -384,13 +384,12 @@ fileprivate extension URLSession._MultiHandle { timeoutSource = nil queue.async { self.timeoutTimerFired() } case .milliseconds(let milliseconds): - if (timeoutSource == nil) || timeoutSource!.milliseconds != milliseconds { - //TODO: Could simply change the existing timer by using DispatchSourceTimer again. - let block = DispatchWorkItem { [weak self] in - self?.timeoutTimerFired() - } - timeoutSource = _TimeoutSource(queue: queue, milliseconds: milliseconds, handler: block) + //TODO: Could simply change the existing timer by using DispatchSourceTimer again. + let block = DispatchWorkItem { [weak self] in + self?.timeoutTimerFired() } + // Note: Previous timer instance would cancel internal Dispatch timer in deinit + timeoutSource = _TimeoutSource(queue: queue, milliseconds: milliseconds, handler: block) } } enum _Timeout {