Strange DispatchTime bug

On Linux (Ubuntu 16.04) and swift distributions from 3.0.2 to the latest 4.0 snapshot, I’m seeing incorrect behaviour involving DispatchTime.distantFuture:
(also: https://bugs.swift.org/browse/SR-5706)

···

***
import Dispatch

let now = DispatchTime.now()
let future = DispatchTime.distantFuture
assert(now != future, "this is not the distant future")

print(String(now.rawValue, radix: 16)) // 1c20d6bbd3a (e.g.)
print(String(future.rawValue, radix: 16)) // ffffffffffffffff

print(now < future) // false (incorrect)
print(future < now) // false

print(now > future) // false
print(future > now) // false (incorrect)

extension DispatchTime {
  public static func compare(_ a: DispatchTime, happensBefore b: DispatchTime) -> Bool {
    return a.rawValue < b.rawValue
  }
}

print(DispatchTime.compare(now, happensBefore: future)) // true
print(DispatchTime.compare(future, happensBefore: now)) // false
***

Note that the static func I defined above is essentially the same as the less-than operator as defined in the libdispatch overlay: <https://github.com/apple/swift/blob/92f750aa3c3c4dce47eb55068850f3d1127b16bd/stdlib/public/SDK/Dispatch/Time.swift#L73>

Also, there is a test that should catch this problem:<https://github.com/apple/swift/blob/92f750aa3c3c4dce47eb55068850f3d1127b16bd/test/stdlib/Dispatch.swift#L104>

Could this operator func somehow be called correctly during testing, but incorrectly at runtime?
(In other words, I don’t see where the fix needs to be.)

Thanks,
Guillaume Lessard

Hi Guillaume,

Without going into details, it looks like the Swift wrappers for dispatch_time_t are very, very broken. In short, dispatch_time_t (in the C world) is intentionally documented as an opaque type, but the Swift wrappers assume otherwise and jump to wrong conclusions about the implementation of the type. What this means in practice is that you should avoid the DispatchTime comparison APIs for now.

Dave

···

On Aug 26, 2017, at 15:21, Guillaume Lessard via swift-dev <swift-dev@swift.org> wrote:

On Linux (Ubuntu 16.04) and swift distributions from 3.0.2 to the latest 4.0 snapshot, I’m seeing incorrect behaviour involving DispatchTime.distantFuture:
(also: https://bugs.swift.org/browse/SR-5706)

***
import Dispatch

let now = DispatchTime.now()
let future = DispatchTime.distantFuture
assert(now != future, "this is not the distant future")

print(String(now.rawValue, radix: 16)) // 1c20d6bbd3a (e.g.)
print(String(future.rawValue, radix: 16)) // ffffffffffffffff

print(now < future) // false (incorrect)
print(future < now) // false

print(now > future) // false
print(future > now) // false (incorrect)

extension DispatchTime {
public static func compare(_ a: DispatchTime, happensBefore b: DispatchTime) -> Bool {
   return a.rawValue < b.rawValue
}
}

print(DispatchTime.compare(now, happensBefore: future)) // true
print(DispatchTime.compare(future, happensBefore: now)) // false
***

Note that the static func I defined above is essentially the same as the less-than operator as defined in the libdispatch overlay: <https://github.com/apple/swift/blob/92f750aa3c3c4dce47eb55068850f3d1127b16bd/stdlib/public/SDK/Dispatch/Time.swift#L73>

Also, there is a test that should catch this problem:<https://github.com/apple/swift/blob/92f750aa3c3c4dce47eb55068850f3d1127b16bd/test/stdlib/Dispatch.swift#L104>

Could this operator func somehow be called correctly during testing, but incorrectly at runtime?
(In other words, I don’t see where the fix needs to be.)

Thanks,
Guillaume Lessard

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Hi David,

Without going into details, it looks like the Swift wrappers for dispatch_time_t are very, very broken. In short, dispatch_time_t (in the C world) is intentionally documented as an opaque type, but the Swift wrappers assume otherwise and jump to wrong conclusions about the implementation of the type. What this means in practice is that you should avoid the DispatchTime comparison APIs for now.

They’re not *that* opaque, they’re here:
<https://github.com/apple/swift-corelibs-libdispatch/blob/0fd5a69ee5f9597aeaff8aa3f48021ced022db15/src/time.c#L93> and
<https://github.com/apple/swift-corelibs-libdispatch/blob/0fd5a69ee5f9597aeaff8aa3f48021ced022db15/src/time.c#L136>

In any event, the DispatchTime and DispatchWallTime wrappers do not let you initialize them from a raw value and, as such, avoid the duality of dispatch_time_t.

In my example, the runtime is probably not running the comparator it’s supposed to
(the one at https://github.com/apple/swift/blob/92f750aa3c3c4dce47eb55068850f3d1127b16bd/stdlib/public/SDK/Dispatch/Time.swift#L73). We can observe what the values are: some int in the range 1..<(2^63), and 2^64-1. The latter is always greater than the former, yet we’re getting `false` from a less-than operator. Strange.

Guillaume Lessard

···

On Aug 26, 2017, at 15:36, David Zarzycki <zarzycki@icloud.com> wrote: