Skip to content

Commit

Permalink
Work around Xcode 13 GM SDK issues. (#1964)
Browse files Browse the repository at this point in the history
Motivation:

This is a backport of #1956.

Xcode 13 GM shipped with a Swift overlay for libsystem in macOS that
marked free's first argument as non-nullable. This leads to an awkward
breakage for us, because we're trying to hold a reference to free as a
function pointer, and to do that we had an explicit type annotation.

We'd like to keep NIO compiling in Xcode 13 GM.

Modifications:

- Defined the free function as a thunk that passes through to the
  underlying OS free call, but takes its first argument as non-nullable.

Result:

Should compile on the Xcode 13 GM again.

Co-authored-by: Cory Benfield <[email protected]>
  • Loading branch information
baarde and Lukasa authored Sep 21, 2021
1 parent 6699571 commit 546610d
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 7 deletions.
10 changes: 7 additions & 3 deletions Sources/NIO/ByteBuffer-core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@

let sysMalloc: @convention(c) (size_t) -> UnsafeMutableRawPointer? = malloc
let sysRealloc: @convention(c) (UnsafeMutableRawPointer?, size_t) -> UnsafeMutableRawPointer? = realloc
let sysFree: @convention(c) (UnsafeMutableRawPointer?) -> Void = free

/// Xcode 13 GM shipped with a bug in the SDK that caused `free`'s first argument to be annotated as
/// non-nullable. To that end, we define a thunk through to `free` that matches that constraint, as we
/// never pass a `nil` pointer to it.
let sysFree: @convention(c) (UnsafeMutableRawPointer) -> Void = { free($0) }

#if !swift(>=4.1)
public extension UnsafeMutableRawPointer {
Expand Down Expand Up @@ -114,7 +118,7 @@ public struct ByteBufferAllocator {

internal init(hookedMalloc: @escaping @convention(c) (size_t) -> UnsafeMutableRawPointer?,
hookedRealloc: @escaping @convention(c) (UnsafeMutableRawPointer?, size_t) -> UnsafeMutableRawPointer?,
hookedFree: @escaping @convention(c) (UnsafeMutableRawPointer?) -> Void,
hookedFree: @escaping @convention(c) (UnsafeMutableRawPointer) -> Void,
hookedMemcpy: @escaping @convention(c) (UnsafeMutableRawPointer, UnsafeRawPointer, size_t) -> Void) {
self.malloc = hookedMalloc
self.realloc = hookedRealloc
Expand All @@ -132,7 +136,7 @@ public struct ByteBufferAllocator {

internal let malloc: @convention(c) (size_t) -> UnsafeMutableRawPointer?
internal let realloc: @convention(c) (UnsafeMutableRawPointer?, size_t) -> UnsafeMutableRawPointer?
internal let free: @convention(c) (UnsafeMutableRawPointer?) -> Void
internal let free: @convention(c) (UnsafeMutableRawPointer) -> Void
internal let memcpy: @convention(c) (UnsafeMutableRawPointer, UnsafeRawPointer, size_t) -> Void

}
Expand Down
6 changes: 3 additions & 3 deletions Tests/NIOTests/ByteBufferTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1646,11 +1646,11 @@ private enum AllocationExpectationState: Int {
}

private var testAllocationOfReallyBigByteBuffer_state = AllocationExpectationState.begin
private func testAllocationOfReallyBigByteBuffer_freeHook(_ ptr: UnsafeMutableRawPointer?) -> Void {
private func testAllocationOfReallyBigByteBuffer_freeHook(_ ptr: UnsafeMutableRawPointer) -> Void {
precondition(AllocationExpectationState.reallocDone == testAllocationOfReallyBigByteBuffer_state)
testAllocationOfReallyBigByteBuffer_state = .freeDone
/* free the pointer initially produced by malloc and then rebased by realloc offsetting it back */
free(ptr?.advanced(by: Int(Int32.max)))
free(ptr.advanced(by: Int(Int32.max)))
}

private func testAllocationOfReallyBigByteBuffer_mallocHook(_ size: Int) -> UnsafeMutableRawPointer? {
Expand All @@ -1674,7 +1674,7 @@ private func testAllocationOfReallyBigByteBuffer_memcpyHook(_ dst: UnsafeMutable

private var testReserveCapacityLarger_reallocCount = 0
private var testReserveCapacityLarger_mallocCount = 0
private func testReserveCapacityLarger_freeHook( _ ptr: UnsafeMutableRawPointer?) -> Void {
private func testReserveCapacityLarger_freeHook( _ ptr: UnsafeMutableRawPointer) -> Void {
free(ptr)
}

Expand Down
2 changes: 1 addition & 1 deletion Tests/NIOTests/CodecTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import XCTest

private var testDecoderIsNotQuadratic_mallocs = 0
private var testDecoderIsNotQuadratic_reallocs = 0
private func testDecoderIsNotQuadratic_freeHook(_ ptr: UnsafeMutableRawPointer?) -> Void {
private func testDecoderIsNotQuadratic_freeHook(_ ptr: UnsafeMutableRawPointer) -> Void {
free(ptr)
}

Expand Down

0 comments on commit 546610d

Please sign in to comment.