Skip to content

Commit 75ba01b

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 b8f1534 commit 75ba01b

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
@@ -66,7 +66,11 @@ public struct DispatchData : RandomAccessCollection {
6666
}
6767

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

7276
public var count: Int {
@@ -111,7 +115,7 @@ public struct DispatchData : RandomAccessCollection {
111115
/// - parameter data: The data to append to this data.
112116
public mutating func append(_ other: DispatchData) {
113117
let data = CDispatch.dispatch_data_create_concat(__wrapped.__wrapped, other.__wrapped.__wrapped)
114-
__wrapped = __DispatchData(data: data)
118+
__wrapped = __DispatchData(data: data, owned: true)
115119
}
116120

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

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)