Skip to content

Commit 3efce58

Browse files
committed
SR-2656: extra releases of dispatch_data_t objects on Linux
Fixes an over-release problem in the wrapping overlay that occurred in callback blocks that take DispatchData structs. Just going through the glue layer between the Swift and C APIs should not result in a net change in the reference count of the dispatch_data_t object that the CDispatch layer is giving us to hand to the Swift callback block. However, when the temporary DispatchData struct we created in the wrapping layer (and its wrapped __DispatchData object) went out of scope at the end of the callback, the dispatch_data_t was released by __DispatchData's deinit resulting in an unintended net -1 from the glue code. We either need to add a compensating retain before entering the callback block or suppress the release in the deinit. This patch suppresses the release by adding an internal init that can create DispatchData's with borrowed dispatch_data_t objects that are not released on deinitialization.
1 parent 6a6b794 commit 3efce58

File tree

3 files changed

+17
-9
lines changed

3 files changed

+17
-9
lines changed

src/swift/Data.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ public struct DispatchData : RandomAccessCollection {
6565
}
6666

6767
internal init(data: dispatch_data_t) {
68-
__wrapped = __DispatchData(data: data)
68+
__wrapped = __DispatchData(data: data, owned: true)
69+
}
70+
71+
internal init(borrowedData: dispatch_data_t) {
72+
__wrapped = __DispatchData(data: borrowedData, owned: false)
6973
}
7074

7175
public var count: Int {
@@ -110,7 +114,7 @@ public struct DispatchData : RandomAccessCollection {
110114
/// - parameter data: The data to append to this data.
111115
public mutating func append(_ other: DispatchData) {
112116
let data = CDispatch.dispatch_data_create_concat(__wrapped.__wrapped, other.__wrapped.__wrapped)
113-
__wrapped = __DispatchData(data: data)
117+
__wrapped = __DispatchData(data: data, owned: true)
114118
}
115119

116120
/// Append a buffer of bytes to the data.
@@ -244,7 +248,7 @@ public struct DispatchDataIterator : IteratorProtocol, Sequence {
244248
public init(_data: DispatchData) {
245249
var ptr: UnsafeRawPointer?
246250
self._count = 0
247-
self._data = __DispatchData(data: CDispatch.dispatch_data_create_map(_data.__wrapped.__wrapped, &ptr, &self._count))
251+
self._data = __DispatchData(data: CDispatch.dispatch_data_create_map(_data.__wrapped.__wrapped, &ptr, &self._count), owned: true)
248252
self._ptr = ptr
249253
self._position = _data.startIndex
250254

src/swift/IO.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ public extension DispatchIO {
3636

3737
public class func read(fromFileDescriptor: Int32, maxLength: Int, runningHandlerOn queue: DispatchQueue, handler: @escaping (_ data: DispatchData, _ error: Int32) -> Void) {
3838
dispatch_read(fromFileDescriptor, maxLength, queue.__wrapped) { (data: dispatch_data_t, error: Int32) in
39-
handler(DispatchData(data: data), error)
39+
handler(DispatchData(borrowedData: data), error)
4040
}
4141
}
4242

4343
public class func write(toFileDescriptor: Int32, data: DispatchData, runningHandlerOn queue: DispatchQueue, handler: @escaping (_ data: DispatchData?, _ error: Int32) -> Void) {
4444
dispatch_write(toFileDescriptor, data.__wrapped.__wrapped, queue.__wrapped) { (data: dispatch_data_t?, error: Int32) in
45-
handler(data.flatMap { DispatchData(data: $0) }, error)
45+
handler(data.flatMap { DispatchData(borrowedData: $0) }, error)
4646
}
4747
}
4848

@@ -77,13 +77,13 @@ public extension DispatchIO {
7777

7878
public func read(offset: off_t, length: Int, queue: DispatchQueue, ioHandler: @escaping (_ done: Bool, _ data: DispatchData?, _ error: Int32) -> Void) {
7979
dispatch_io_read(self.__wrapped, offset, length, queue.__wrapped) { (done: Bool, data: dispatch_data_t?, error: Int32) in
80-
ioHandler(done, data.flatMap { DispatchData(data: $0) }, error)
80+
ioHandler(done, data.flatMap { DispatchData(borrowedData: $0) }, error)
8181
}
8282
}
8383

8484
public func write(offset: off_t, data: DispatchData, queue: DispatchQueue, ioHandler: @escaping (_ done: Bool, _ data: DispatchData?, _ error: Int32) -> Void) {
8585
dispatch_io_write(self.__wrapped, offset, data.__wrapped.__wrapped, queue.__wrapped) { (done: Bool, data: dispatch_data_t?, error: Int32) in
86-
ioHandler(done, data.flatMap { DispatchData(data: $0) }, error)
86+
ioHandler(done, data.flatMap { DispatchData(borrowedData: $0) }, error)
8787
}
8888
}
8989

src/swift/Wrapper.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,21 @@ extension DispatchSource : DispatchSourceProcess,
192192

193193
internal class __DispatchData : DispatchObject {
194194
internal let __wrapped:dispatch_data_t
195+
internal let __owned:Bool
195196

196197
final internal override func wrapped() -> dispatch_object_t {
197198
return unsafeBitCast(__wrapped, to: dispatch_object_t.self)
198199
}
199200

200-
internal init(data:dispatch_data_t) {
201+
internal init(data:dispatch_data_t, owned:Bool) {
201202
__wrapped = data
203+
__owned = owned
202204
}
203205

204206
deinit {
205-
_swift_dispatch_release(wrapped())
207+
if __owned {
208+
_swift_dispatch_release(wrapped())
209+
}
206210
}
207211
}
208212

0 commit comments

Comments
 (0)