Skip to content

Commit 69c965e

Browse files
committed
[Concurrency] Don't pass negative times to the Dispatch code.
Dispatch uses unsigned times, and cannot cope with times before its clock started. As such, passing negative times from Swift through to the C++ code results in large unsigned values, which then causes us to wait forever. This is undesirable. rdar://148899609
1 parent cc8639b commit 69c965e

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

stdlib/public/Concurrency/DispatchExecutor.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,20 +161,29 @@ enum DispatchClockID: CInt {
161161
@available(SwiftStdlib 6.2, *)
162162
extension DispatchExecutorProtocol {
163163

164+
func clamp(_ components: (seconds: Int64, attoseconds: Int64))
165+
-> (seconds: Int64, attoseconds: Int64) {
166+
if components.seconds < 0
167+
|| components.seconds == 0 && components.attoseconds < 0 {
168+
return (seconds: 0, attoseconds: 0)
169+
}
170+
return (seconds: components.seconds, attoseconds: components.attoseconds)
171+
}
172+
164173
func timestamp<C: Clock>(for instant: C.Instant, clock: C)
165174
-> (clockID: DispatchClockID, seconds: Int64, nanoseconds: Int64) {
166175
if clock.traits.contains(.continuous) {
167176
let dispatchClock: ContinuousClock = .continuous
168177
let instant = dispatchClock.convert(instant: instant, from: clock)!
169-
let (seconds, attoseconds) = instant._value.components
178+
let (seconds, attoseconds) = clamp(instant._value.components)
170179
let nanoseconds = attoseconds / 1_000_000_000
171180
return (clockID: .continuous,
172181
seconds: Int64(seconds),
173182
nanoseconds: Int64(nanoseconds))
174183
} else {
175184
let dispatchClock: SuspendingClock = .suspending
176185
let instant = dispatchClock.convert(instant: instant, from: clock)!
177-
let (seconds, attoseconds) = instant._value.components
186+
let (seconds, attoseconds) = clamp(instant._value.components)
178187
let nanoseconds = attoseconds / 1_000_000_000
179188
return (clockID: .suspending,
180189
seconds: Int64(seconds),
@@ -185,7 +194,7 @@ extension DispatchExecutorProtocol {
185194
func delay<C: Clock>(from duration: C.Duration, clock: C)
186195
-> (seconds: Int64, nanoseconds: Int64) {
187196
let swiftDuration = clock.convert(from: duration)!
188-
let (seconds, attoseconds) = swiftDuration.components
197+
let (seconds, attoseconds) = clamp(swiftDuration.components)
189198
let nanoseconds = attoseconds / 1_000_000_000
190199
return (seconds: seconds, nanoseconds: nanoseconds)
191200
}

0 commit comments

Comments
 (0)