Skip to content

Commit 8a8552f

Browse files
authored
Merge pull request #129 from glessard/reenable-mach-port
Re-enable Mach.Port
2 parents 547b2a5 + ad40724 commit 8a8552f

File tree

2 files changed

+198
-77
lines changed

2 files changed

+198
-77
lines changed

Sources/System/MachPort.swift

Lines changed: 68 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
See https://swift.org/LICENSE.txt for license information
88
*/
99

10-
#if false && swift(>=5.8) && $MoveOnly && (os(macOS) || os(iOS) || os(watchOS) || os(tvOS))
10+
#if swift(>=5.9) && (os(macOS) || os(iOS) || os(watchOS) || os(tvOS))
1111

1212
import Darwin.Mach
1313

@@ -48,11 +48,13 @@ public enum Mach {
4848
///
4949
/// This initializer makes a syscall to guard the right.
5050
public init(name: mach_port_name_t) {
51-
precondition(name != mach_port_name_t(MACH_PORT_NULL), "Mach.Port cannot be initialized with MACH_PORT_NULL")
51+
precondition(name != mach_port_name_t(MACH_PORT_NULL),
52+
"Mach.Port cannot be initialized with MACH_PORT_NULL")
5253
self._name = name
5354

5455
if RightType.self == ReceiveRight.self {
55-
precondition(name != 0xFFFFFFFF /* MACH_PORT_DEAD */, "Receive rights cannot be dead names")
56+
precondition(name != 0xFFFFFFFF /* MACH_PORT_DEAD */,
57+
"Receive rights cannot be dead names")
5658

5759
let secret = mach_port_context_t(arc4random())
5860
_machPrecondition(mach_port_guard(mach_task_self_, name, secret, 0))
@@ -81,17 +83,18 @@ public enum Mach {
8183
}
8284

8385
deinit {
84-
if _name == 0xFFFFFFFF /* MACH_PORT_DEAD */ {
85-
precondition(RightType.self != ReceiveRight.self, "Receive rights cannot be dead names")
86-
_machPrecondition(mach_port_mod_refs(mach_task_self_, _name, MACH_PORT_RIGHT_DEAD_NAME, -1))
86+
if RightType.self == ReceiveRight.self {
87+
precondition(_name != 0xFFFFFFFF /* MACH_PORT_DEAD */,
88+
"Receive rights cannot be dead names")
89+
_machPrecondition(
90+
mach_port_destruct(mach_task_self_, _name, 0, _context)
91+
)
8792
} else {
88-
if RightType.self == ReceiveRight.self {
89-
_machPrecondition(mach_port_destruct(mach_task_self_, _name, -1, _context))
90-
} else if RightType.self == SendRight.self {
91-
_machPrecondition(mach_port_mod_refs(mach_task_self_, _name, MACH_PORT_RIGHT_SEND, -1))
92-
} else if RightType.self == SendOnceRight.self {
93-
_machPrecondition(mach_port_mod_refs(mach_task_self_, _name, MACH_PORT_RIGHT_SEND_ONCE, -1))
94-
}
93+
assert(
94+
RightType.self == SendRight.self ||
95+
RightType.self == SendOnceRight.self
96+
)
97+
_machPrecondition(mach_port_deallocate(mach_task_self_, _name))
9598
}
9699
}
97100
}
@@ -135,6 +138,8 @@ extension Mach.Port where RightType == Mach.ReceiveRight {
135138
/// The underlying port right will be automatically deallocated when
136139
/// the Mach.Port object is destroyed.
137140
public init(name: mach_port_name_t, context: mach_port_context_t) {
141+
precondition(name != mach_port_name_t(MACH_PORT_NULL),
142+
"Mach.Port cannot be initialized with MACH_PORT_NULL")
138143
self._name = name
139144
self._context = context
140145
}
@@ -147,9 +152,9 @@ extension Mach.Port where RightType == Mach.ReceiveRight {
147152
@inlinable
148153
public init() {
149154
var storage: mach_port_name_t = mach_port_name_t(MACH_PORT_NULL)
150-
withUnsafeMutablePointer(to: &storage) { storage in
151-
_machPrecondition(mach_port_allocate(mach_task_self_, MACH_PORT_RIGHT_RECEIVE, storage))
152-
}
155+
_machPrecondition(
156+
mach_port_allocate(mach_task_self_, MACH_PORT_RIGHT_RECEIVE, &storage)
157+
)
153158

154159
// name-only init will guard ReceiveRights
155160
self.init(name: storage)
@@ -167,9 +172,11 @@ extension Mach.Port where RightType == Mach.ReceiveRight {
167172
/// After this function completes, the Mach.Port is destroyed and no longer
168173
/// usable.
169174
@inlinable
170-
public __consuming func relinquish(
175+
public consuming func relinquish(
171176
) -> (name: mach_port_name_t, context: mach_port_context_t) {
172-
return (name: _name, context: _context)
177+
let destructured = (name: _name, context: _context)
178+
discard self
179+
return destructured
173180
}
174181

175182
/// Remove guard and transfer ownership of the underlying port right to
@@ -187,9 +194,10 @@ extension Mach.Port where RightType == Mach.ReceiveRight {
187194
/// Mach.ReceiveRights. Use relinquish() to avoid the syscall and extract
188195
/// the context value along with the port name.
189196
@inlinable
190-
public __consuming func unguardAndRelinquish() -> mach_port_name_t {
191-
_machPrecondition(mach_port_unguard(mach_task_self_, _name, _context))
192-
return _name
197+
public consuming func unguardAndRelinquish() -> mach_port_name_t {
198+
let (name, context) = self.relinquish()
199+
_machPrecondition(mach_port_unguard(mach_task_self_, name, context))
200+
return name
193201
}
194202

195203
/// Borrow access to the port name in a block that can perform
@@ -220,17 +228,15 @@ extension Mach.Port where RightType == Mach.ReceiveRight {
220228
var newRight: mach_port_name_t = mach_port_name_t(MACH_PORT_NULL)
221229
var newRightType: mach_port_type_t = MACH_PORT_TYPE_NONE
222230

223-
withUnsafeMutablePointer(to: &newRight) { newRight in
224-
withUnsafeMutablePointer(to: &newRightType) { newRightType in
225-
_machPrecondition(
226-
mach_port_extract_right(mach_task_self_,
227-
_name,
228-
mach_msg_type_name_t(MACH_MSG_TYPE_MAKE_SEND_ONCE),
229-
newRight,
230-
newRightType)
231-
)
232-
}
233-
}
231+
_machPrecondition(
232+
mach_port_extract_right(
233+
mach_task_self_,
234+
_name,
235+
mach_msg_type_name_t(MACH_MSG_TYPE_MAKE_SEND_ONCE),
236+
&newRight,
237+
&newRightType
238+
)
239+
)
234240

235241
// The value of newRight is validated by the Mach.Port initializer
236242
precondition(newRightType == MACH_MSG_TYPE_MOVE_SEND_ONCE)
@@ -249,7 +255,11 @@ extension Mach.Port where RightType == Mach.ReceiveRight {
249255
let how = MACH_MSG_TYPE_MAKE_SEND
250256

251257
// name is the same because send and recv rights are coalesced
252-
_machPrecondition(mach_port_insert_right(mach_task_self_, _name, _name, mach_msg_type_name_t(how)))
258+
_machPrecondition(
259+
mach_port_insert_right(
260+
mach_task_self_, _name, _name, mach_msg_type_name_t(how)
261+
)
262+
)
253263

254264
return Mach.Port(name: _name)
255265
}
@@ -261,11 +271,19 @@ extension Mach.Port where RightType == Mach.ReceiveRight {
261271
public var makeSendCount: mach_port_mscount_t {
262272
get {
263273
var status: mach_port_status = mach_port_status()
264-
var size: mach_msg_type_number_t = mach_msg_type_number_t(MemoryLayout<mach_port_status>.size / MemoryLayout<natural_t>.size)
265-
withUnsafeMutablePointer(to: &size) { size in
266-
withUnsafeMutablePointer(to: &status) { status in
267-
let info = UnsafeMutableRawPointer(status).bindMemory(to: integer_t.self, capacity: 1)
268-
_machPrecondition(mach_port_get_attributes(mach_task_self_, _name, MACH_PORT_RECEIVE_STATUS, info, size))
274+
var size = mach_msg_type_number_t(
275+
MemoryLayout<mach_port_status>.size / MemoryLayout<natural_t>.size
276+
)
277+
278+
withUnsafeMutablePointer(to: &status) {
279+
let status = UnsafeMutableBufferPointer(start: $0, count: 1)
280+
status.withMemoryRebound(to: integer_t.self) {
281+
let info = $0.baseAddress
282+
_machPrecondition(
283+
mach_port_get_attributes(
284+
mach_task_self_, _name, MACH_PORT_RECEIVE_STATUS, info, &size
285+
)
286+
)
269287
}
270288
}
271289
return status.mps_mscount
@@ -288,8 +306,10 @@ extension Mach.Port where RightType == Mach.SendRight {
288306
/// After this function completes, the Mach.Port is destroyed and no longer
289307
/// usable.
290308
@inlinable
291-
public __consuming func relinquish() -> mach_port_name_t {
292-
return _name
309+
public consuming func relinquish() -> mach_port_name_t {
310+
let name = _name
311+
discard self
312+
return name
293313
}
294314

295315
/// Create another send right from a given send right.
@@ -304,8 +324,10 @@ extension Mach.Port where RightType == Mach.SendRight {
304324
let how = MACH_MSG_TYPE_COPY_SEND
305325

306326
// name is the same because send rights are coalesced
307-
let kr = mach_port_insert_right(mach_task_self_, _name, _name, mach_msg_type_name_t(how))
308-
if kr == KERN_INVALID_CAPABILITY {
327+
let kr = mach_port_insert_right(
328+
mach_task_self_, _name, _name, mach_msg_type_name_t(how)
329+
)
330+
if kr == KERN_INVALID_NAME || kr == KERN_INVALID_CAPABILITY {
309331
throw Mach.PortRightError.deadName
310332
}
311333
_machPrecondition(kr)
@@ -326,8 +348,10 @@ extension Mach.Port where RightType == Mach.SendOnceRight {
326348
/// After this function completes, the Mach.Port is destroyed and no longer
327349
/// usable.
328350
@inlinable
329-
public __consuming func relinquish() -> mach_port_name_t {
330-
return _name
351+
public consuming func relinquish() -> mach_port_name_t {
352+
let name = _name
353+
discard self
354+
return name
331355
}
332356
}
333357

0 commit comments

Comments
 (0)