Skip to content

Commit a7504ee

Browse files
dgrove-ossdas
authored andcommitted
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. Signed-off-by: Daniel A. Steffen <dsteffen@apple.com>
1 parent 670c2a6 commit a7504ee

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.
@@ -247,7 +251,7 @@ public struct DispatchDataIterator : IteratorProtocol, Sequence {
247251
public init(_data: DispatchData) {
248252
var ptr: UnsafeRawPointer?
249253
self._count = 0
250-
self._data = __DispatchData(data: CDispatch.dispatch_data_create_map(_data.__wrapped.__wrapped, &ptr, &self._count))
254+
self._data = __DispatchData(data: CDispatch.dispatch_data_create_map(_data.__wrapped.__wrapped, &ptr, &self._count), owned: true)
251255
self._ptr = ptr
252256
self._position = _data.startIndex
253257

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
@@ -188,17 +188,21 @@ extension DispatchSource : DispatchSourceProcess,
188188

189189
internal class __DispatchData : DispatchObject {
190190
internal let __wrapped:dispatch_data_t
191+
internal let __owned:Bool
191192

192193
final internal override func wrapped() -> dispatch_object_t {
193194
return unsafeBitCast(__wrapped, to: dispatch_object_t.self)
194195
}
195196

196-
internal init(data:dispatch_data_t) {
197+
internal init(data:dispatch_data_t, owned:Bool) {
197198
__wrapped = data
199+
__owned = owned
198200
}
199201

200202
deinit {
201-
_swift_dispatch_release(wrapped())
203+
if __owned {
204+
_swift_dispatch_release(wrapped())
205+
}
202206
}
203207
}
204208

0 commit comments

Comments
 (0)