I'm trying to make a Swifty wrapper for sysctl
, and I think I ran into a use-case for UnsafeMutablePointer.init(mutating:)
. My initial code requires keys
be mutable, even though sysctl
doesn't actually mutate them:
func getProcessInfo(for pid: pid_t) throws -> kinfo_proc {
var keys = [CTL_KERN, KERN_PROC, KERN_PROC_PID, pid]
var processInfo = kinfo_proc()
var requiredSize = MemoryLayout.size(ofValue: processInfo)
os_signpost(.begin, log: SignPosts.pointsOfInterestLog,
name: "sysctl - get process info")
let result = Darwin.sysctl(
&keys, // <- The pointer in question
UInt32(keys.count),
&processInfo,
&requiredSize,
nil,
0
)
os_signpost(.end, log: SignPosts.pointsOfInterestLog,
name: "sysctl - get process info")
guard result == 0 else { throw POSIXErrorCode(rawValue: errno).asError }
guard requiredSize == MemoryLayout.size(ofValue: processInfo) else { throw PosixError.unknown }
guard processInfo.kp_proc.p_pid == pid else { throw PosixError.unknown }
return processInfo
}
I though I could replace &keys
with UnsafeMutablePointer<Int32>(mutating: &keys)
, but that yields a warning:
Initialization of 'UnsafeMutablePointer' results in a dangling pointer
hich I think is because the lifetime of keys
exists long enough for the call to UnsafeMutablePointer.init(mutating:)
, but not for the call to sysctl
.
I suppose one alternative is:
func getProcessInfo(for pid: pid_t) throws -> kinfo_proc {
let keys = [CTL_KERN, KERN_PROC, KERN_PROC_PID, pid]
var processInfo = kinfo_proc()
var requiredSize = MemoryLayout.size(ofValue: processInfo)
try keys.withUnsafeBufferPointer { keysBuffer in
os_signpost(.begin, log: SignPosts.pointsOfInterestLog,
name: "sysctl - get process info")
let result = Darwin.sysctl(
UnsafeMutablePointer<Int32>(mutating: keysBuffer.baseAddress!),
UInt32(keys.count),
&processInfo,
&requiredSize,
nil,
0
)
os_signpost(.end, log: SignPosts.pointsOfInterestLog,
name: "sysctl - get process info")
guard result == 0 else { throw POSIXErrorCode(rawValue: errno).asError }
guard requiredSize == MemoryLayout.size(ofValue: processInfo) else { throw PosixError.unknown }
guard processInfo.kp_proc.p_pid == pid else { throw PosixError.unknown }
}
return processInfo
}
Is there some function like withoutActuallyEscaping(_:do:)
, but like withoutActuallyMutating
, with a sufficient lifetime to make a call like this, or is this code my best bet?