dispatch_block_t is imported wrong, breaks barrier blocks (SR-2246)


(Lily Ballard) #1

I just filed SR-2246 about how `queue.async(flags: .barrier)` is completely broken, and I think the problem comes down to `dispatch_block_t` is being imported as `() -> ()` instead of as `@convention(block) () -> ()`, and therefore `__dispatch_async` has the type `(DispatchQueue, () -> Void) -> Void` instead of `(DispatchQueue, @convention(block) () -> Void) -> Void`.

The reason I'm sending this email is because I'd like to fix this, but I have no idea how. In Swift 2.x the SDK overlay had an explicit definition for `dispatch_block_t` instead of importing it from the C header, but with the new Dispatch API, it seems to be relying on the clang importer to get __dispatch_async and friends (though I'm not sure what causes the __ prefix since dispatch_async doesn't seem to have the relevant attribute). Swift 2.2 had a typealias for dispatch_block_t, but Swift 3 marks dispatch_block_t as being unavailable (although again I don't know how since I don't see the relevant attribute in the macOS SDK), so presumably reintroducing a typealias isn't a good idea, if it even works at all.

-Kevin Ballard


(Lily Ballard) #2

Hmm. The implementation of DispatchQueue.async(execute: DispatchWorkItem) is as follows:

  public func async(execute workItem: DispatchWorkItem) {
    // _swift_dispatch_async preserves the @convention(block)
    // for work item blocks.
    _swift_dispatch_async(self, workItem._block)
  }

This comment indicates that someone was already aware of the problem and fixed it in some places but not all. This also suggests that the problem itself can be fixed merely by replacing the remaining uses of __dispatch_async with _swift_dispatch_async(). I will try this out.

-Kevin

···

On Mon, Aug 1, 2016, at 02:53 PM, Kevin Ballard via swift-dev wrote:

I just filed SR-2246 about how `queue.async(flags: .barrier)` is completely broken, and I think the problem comes down to `dispatch_block_t` is being imported as `() -> ()` instead of as `@convention(block) () -> ()`, and therefore `__dispatch_async` has the type `(DispatchQueue, () -> Void) -> Void` instead of `(DispatchQueue, @convention(block) () -> Void) -> Void`.

The reason I'm sending this email is because I'd like to fix this, but I have no idea how. In Swift 2.x the SDK overlay had an explicit definition for `dispatch_block_t` instead of importing it from the C header, but with the new Dispatch API, it seems to be relying on the clang importer to get __dispatch_async and friends (though I'm not sure what causes the __ prefix since dispatch_async doesn't seem to have the relevant attribute). Swift 2.2 had a typealias for dispatch_block_t, but Swift 3 marks dispatch_block_t as being unavailable (although again I don't know how since I don't see the relevant attribute in the macOS SDK), so presumably reintroducing a typealias isn't a good idea, if it even works at all.

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


(Lily Ballard) #3

For anyone following along, I've submitted a PR to fix this as https://github.com/apple/swift/pull/3923.

-Kevin

···

On Mon, Aug 1, 2016, at 03:04 PM, Kevin Ballard wrote:

Hmm. The implementation of DispatchQueue.async(execute: DispatchWorkItem) is as follows:

  public func async(execute workItem: DispatchWorkItem) {
    // _swift_dispatch_async preserves the @convention(block)
    // for work item blocks.
    _swift_dispatch_async(self, workItem._block)
  }

This comment indicates that someone was already aware of the problem and fixed it in some places but not all. This also suggests that the problem itself can be fixed merely by replacing the remaining uses of __dispatch_async with _swift_dispatch_async(). I will try this out.

-Kevin

On Mon, Aug 1, 2016, at 02:53 PM, Kevin Ballard via swift-dev wrote:
> I just filed SR-2246 about how `queue.async(flags: .barrier)` is completely broken, and I think the problem comes down to `dispatch_block_t` is being imported as `() -> ()` instead of as `@convention(block) () -> ()`, and therefore `__dispatch_async` has the type `(DispatchQueue, () -> Void) -> Void` instead of `(DispatchQueue, @convention(block) () -> Void) -> Void`.
>
> The reason I'm sending this email is because I'd like to fix this, but I have no idea how. In Swift 2.x the SDK overlay had an explicit definition for `dispatch_block_t` instead of importing it from the C header, but with the new Dispatch API, it seems to be relying on the clang importer to get __dispatch_async and friends (though I'm not sure what causes the __ prefix since dispatch_async doesn't seem to have the relevant attribute). Swift 2.2 had a typealias for dispatch_block_t, but Swift 3 marks dispatch_block_t as being unavailable (although again I don't know how since I don't see the relevant attribute in the macOS SDK), so presumably reintroducing a typealias isn't a good idea, if it even works at all.
>
> -Kevin Ballard
> _______________________________________________
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev


(Jordan Rose) #4

I’d suggest putting this over on swift-corelibs-dev, since it’s a Dispatch-specific issue.

Jordan

···

On Aug 1, 2016, at 17:25, Kevin Ballard via swift-dev <swift-dev@swift.org> wrote:

For anyone following along, I've submitted a PR to fix this as https://github.com/apple/swift/pull/3923.

-Kevin

On Mon, Aug 1, 2016, at 03:04 PM, Kevin Ballard wrote:

Hmm. The implementation of DispatchQueue.async(execute: DispatchWorkItem) is as follows:

  public func async(execute workItem: DispatchWorkItem) {
    // _swift_dispatch_async preserves the @convention(block)
    // for work item blocks.
    _swift_dispatch_async(self, workItem._block)
  }

This comment indicates that someone was already aware of the problem and fixed it in some places but not all. This also suggests that the problem itself can be fixed merely by replacing the remaining uses of __dispatch_async with _swift_dispatch_async(). I will try this out.

-Kevin

On Mon, Aug 1, 2016, at 02:53 PM, Kevin Ballard via swift-dev wrote:

I just filed SR-2246 about how `queue.async(flags: .barrier)` is completely broken, and I think the problem comes down to `dispatch_block_t` is being imported as `() -> ()` instead of as `@convention(block) () -> ()`, and therefore `__dispatch_async` has the type `(DispatchQueue, () -> Void) -> Void` instead of `(DispatchQueue, @convention(block) () -> Void) -> Void`.

The reason I'm sending this email is because I'd like to fix this, but I have no idea how. In Swift 2.x the SDK overlay had an explicit definition for `dispatch_block_t` instead of importing it from the C header, but with the new Dispatch API, it seems to be relying on the clang importer to get __dispatch_async and friends (though I'm not sure what causes the __ prefix since dispatch_async doesn't seem to have the relevant attribute). Swift 2.2 had a typealias for dispatch_block_t, but Swift 3 marks dispatch_block_t as being unavailable (although again I don't know how since I don't see the relevant attribute in the macOS SDK), so presumably reintroducing a typealias isn't a good idea, if it even works at all.

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

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