Skip to content

Commit 69c25d5

Browse files
committed
Use as a platform-independent term to describe pidfd(Linux)/process handle (Windows)
1 parent d1f7639 commit 69c25d5

File tree

4 files changed

+41
-36
lines changed

4 files changed

+41
-36
lines changed

Sources/Subprocess/Platforms/Subprocess+Linux.swift

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@ extension Configuration {
8888

8989
// Spawn
9090
var pid: pid_t = 0
91-
var processFileDescriptor: PlatformFileDescriptor = -1
91+
var processDescriptor: PlatformFileDescriptor = -1
9292
let spawnError: CInt = possibleExecutablePath.withCString { exePath in
9393
return (self.workingDirectory?.string).withOptionalCString { workingDir in
9494
return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in
9595
return fileDescriptors.withUnsafeBufferPointer { fds in
9696
return _subprocess_fork_exec(
9797
&pid,
98-
&processFileDescriptor,
98+
&processDescriptor,
9999
exePath,
100100
workingDir,
101101
fds.baseAddress!,
@@ -145,7 +145,7 @@ extension Configuration {
145145
let execution = Execution(
146146
processIdentifier: .init(
147147
value: pid,
148-
processFileDescriptor: processFileDescriptor
148+
processDescriptor: processDescriptor
149149
)
150150
)
151151
return SpawnResult(
@@ -191,16 +191,16 @@ extension Configuration {
191191
public struct ProcessIdentifier: Sendable, Hashable {
192192
/// The platform specific process identifier value
193193
public let value: pid_t
194-
internal let processFileDescriptor: PlatformFileDescriptor
194+
internal let processDescriptor: PlatformFileDescriptor
195195

196-
internal init(value: pid_t, processFileDescriptor: PlatformFileDescriptor) {
196+
internal init(value: pid_t, processDescriptor: PlatformFileDescriptor) {
197197
self.value = value
198-
self.processFileDescriptor = processFileDescriptor
198+
self.processDescriptor = processDescriptor
199199
}
200200

201201
internal func close() {
202-
if self.processFileDescriptor > 0 {
203-
_SubprocessCShims.close(self.processFileDescriptor)
202+
if self.processDescriptor > 0 {
203+
_SubprocessCShims.close(self.processDescriptor)
204204
}
205205
}
206206
}
@@ -304,16 +304,16 @@ internal func monitorProcessTermination(
304304
// pidfd is only supported on Linux kernel 5.4 and above
305305
// On older releases, use signalfd so we do not need
306306
// to register anything with epoll
307-
if processIdentifier.processFileDescriptor > 0 {
308-
// Register processFileDescriptor with epoll
307+
if processIdentifier.processDescriptor > 0 {
308+
// Register processDescriptor with epoll
309309
var event = epoll_event(
310310
events: EPOLLIN.rawValue,
311-
data: epoll_data(fd: processIdentifier.processFileDescriptor)
311+
data: epoll_data(fd: processIdentifier.processDescriptor)
312312
)
313313
let rc = epoll_ctl(
314314
storage.epollFileDescriptor,
315315
EPOLL_CTL_ADD,
316-
processIdentifier.processFileDescriptor,
316+
processIdentifier.processDescriptor,
317317
&event
318318
)
319319
if rc != 0 {
@@ -326,7 +326,7 @@ internal func monitorProcessTermination(
326326
}
327327
// Now save the registration
328328
var newState = storage
329-
newState.continuations[processIdentifier.processFileDescriptor] = continuation
329+
newState.continuations[processIdentifier.processDescriptor] = continuation
330330
state = .started(newState)
331331
// No state to resume
332332
return nil
@@ -342,7 +342,7 @@ internal func monitorProcessTermination(
342342
if siginfo.si_pid == 0 && siginfo.si_signo == 0 {
343343
// Save this continuation to be called by signal hander
344344
var newState = storage
345-
newState.continuations[processIdentifier.processFileDescriptor] = continuation
345+
newState.continuations[processIdentifier.processDescriptor] = continuation
346346
state = .started(newState)
347347
return nil
348348
}
@@ -421,7 +421,7 @@ private extension siginfo_t {
421421
// Okay to be unlocked global mutable because this value is only set once like dispatch_once
422422
private nonisolated(unsafe) var _signalPipe: (readEnd: CInt, writeEnd: CInt) = (readEnd: -1, writeEnd: -1)
423423
// Okay to be unlocked global mutable because this value is only set once like dispatch_once
424-
private nonisolated(unsafe) var _waitProcessFileDescriptorSupported = false
424+
private nonisolated(unsafe) var _waitprocessDescriptorSupported = false
425425
private let _processMonitorState: Mutex<ProcessMonitorState> = .init(.notStarted)
426426

427427
private func shutdown() {
@@ -520,8 +520,8 @@ private func monitorThreadFunc(args: UnsafeMutableRawPointer?) -> UnsafeMutableR
520520
}
521521

522522
// P_PIDFD requires Linux Kernel 5.4 and above
523-
if _waitProcessFileDescriptorSupported {
524-
_blockAndWaitForProcessFileDescriptor(targetFileDescriptor, context: context)
523+
if _waitprocessDescriptorSupported {
524+
_blockAndWaitForprocessDescriptor(targetFileDescriptor, context: context)
525525
} else {
526526
_reapAllKnownChildProcesses(targetFileDescriptor, context: context)
527527
}
@@ -573,7 +573,7 @@ private let setup: () = {
573573

574574
// If the current kernel does not support pidfd, fallback to signal handler
575575
// Create the self-pipe that signal handler writes to
576-
if !_isWaitProcessFileDescriptorSupported() {
576+
if !_isWaitprocessDescriptorSupported() {
577577
var pipeCreationError: SubprocessError? = nil
578578
do {
579579
let (readEnd, writeEnd) = try FileDescriptor.pipe()
@@ -612,7 +612,7 @@ private let setup: () = {
612612
}
613613
} else {
614614
// Mark waitid(P_PIDFD) as supported
615-
_waitProcessFileDescriptorSupported = true
615+
_waitprocessDescriptorSupported = true
616616
}
617617
let monitorThreadContext = MonitorThreadContext(
618618
epollFileDescriptor: epollFileDescriptor,
@@ -645,7 +645,7 @@ private func _setupMonitorSignalHandler() {
645645
setup
646646
}
647647

648-
private func _blockAndWaitForProcessFileDescriptor(_ pidfd: CInt, context: MonitorThreadContext) {
648+
private func _blockAndWaitForprocessDescriptor(_ pidfd: CInt, context: MonitorThreadContext) {
649649
var terminationStatus: Result<TerminationStatus, SubprocessError>
650650

651651
var siginfo = siginfo_t()
@@ -760,7 +760,7 @@ private func _reapAllKnownChildProcesses(_ signalFd: CInt, context: MonitorThrea
760760
}
761761
}
762762

763-
internal func _isWaitProcessFileDescriptorSupported() -> Bool {
763+
internal func _isWaitprocessDescriptorSupported() -> Bool {
764764
// waitid(P_PIDFD) is only supported on Linux kernel 5.4 and above
765765
// Prob whether the current system supports it by calling it with self pidfd
766766
// and checking for EINVAL (waitid sets errno to EINVAL if it does not

Sources/Subprocess/Platforms/Subprocess+Unix.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ extension Execution {
117117
try _kill(pid, signal: signal)
118118
} else {
119119
guard _pidfd_send_signal(
120-
processIdentifier.processFileDescriptor,
120+
processIdentifier.processDescriptor,
121121
signal.rawValue
122122
) == 0 else {
123123
throw SubprocessError(

Sources/Subprocess/Platforms/Subprocess+Windows.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ extension Configuration {
136136

137137
let pid = ProcessIdentifier(
138138
value: processInfo.dwProcessId,
139-
processHandle: processInfo.hProcess,
139+
processDescriptor: processInfo.hProcess,
140140
threadHandle: processInfo.hThread
141141
)
142142
let execution = Execution(
@@ -280,7 +280,7 @@ extension Configuration {
280280

281281
let pid = ProcessIdentifier(
282282
value: processInfo.dwProcessId,
283-
processHandle: processInfo.hProcess,
283+
processDescriptor: processInfo.hProcess,
284284
threadHandle: processInfo.hThread
285285
)
286286
let execution = Execution(
@@ -487,7 +487,7 @@ internal func monitorProcessTermination(
487487
guard
488488
RegisterWaitForSingleObject(
489489
&waitHandle,
490-
processIdentifier.processHandle,
490+
processIdentifier.processDescriptor,
491491
callback,
492492
context,
493493
INFINITE,
@@ -505,7 +505,7 @@ internal func monitorProcessTermination(
505505
}
506506

507507
var status: DWORD = 0
508-
guard GetExitCodeProcess(processIdentifier.processHandle, &status) else {
508+
guard GetExitCodeProcess(processIdentifier.processDescriptor, &status) else {
509509
// The child process terminated but we couldn't get its status back.
510510
// Assume generic failure.
511511
return .exited(1)
@@ -523,7 +523,7 @@ extension Execution {
523523
/// Terminate the current subprocess with the given exit code
524524
/// - Parameter exitCode: The exit code to use for the subprocess.
525525
public func terminate(withExitCode exitCode: DWORD) throws {
526-
guard TerminateProcess(self.processIdentifier.processHandle, exitCode) else {
526+
guard TerminateProcess(self.processIdentifier.processDescriptor, exitCode) else {
527527
throw SubprocessError(
528528
code: .init(.failedToTerminate),
529529
underlyingError: .init(rawValue: GetLastError())
@@ -547,7 +547,7 @@ extension Execution {
547547
underlyingError: .init(rawValue: GetLastError())
548548
)
549549
}
550-
guard NTSuspendProcess(self.processIdentifier.processHandle) >= 0 else {
550+
guard NTSuspendProcess(self.processIdentifier.processDescriptor) >= 0 else {
551551
throw SubprocessError(
552552
code: .init(.failedToSuspend),
553553
underlyingError: .init(rawValue: GetLastError())
@@ -571,7 +571,7 @@ extension Execution {
571571
underlyingError: .init(rawValue: GetLastError())
572572
)
573573
}
574-
guard NTResumeProcess(self.processIdentifier.processHandle) >= 0 else {
574+
guard NTResumeProcess(self.processIdentifier.processDescriptor) >= 0 else {
575575
throw SubprocessError(
576576
code: .init(.failedToResume),
577577
underlyingError: .init(rawValue: GetLastError())
@@ -677,21 +677,21 @@ extension Environment {
677677
public struct ProcessIdentifier: Sendable, Hashable {
678678
/// Windows specific process identifier value
679679
public let value: DWORD
680-
internal nonisolated(unsafe) let processHandle: HANDLE
680+
internal nonisolated(unsafe) let processDescriptor: HANDLE
681681
internal nonisolated(unsafe) let threadHandle: HANDLE
682682

683683

684-
internal init(value: DWORD, processHandle: HANDLE, threadHandle: HANDLE) {
684+
internal init(value: DWORD, processDescriptor: HANDLE, threadHandle: HANDLE) {
685685
self.value = value
686-
self.processHandle = processHandle
686+
self.processDescriptor = processDescriptor
687687
self.threadHandle = threadHandle
688688
}
689689

690690
internal func close() {
691691
guard CloseHandle(self.threadHandle) else {
692692
fatalError("Failed to close thread HANDLE: \(SubprocessError.UnderlyingError(rawValue: GetLastError()))")
693693
}
694-
guard CloseHandle(self.processHandle) else {
694+
guard CloseHandle(self.processDescriptor) else {
695695
fatalError("Failed to close process HANDLE: \(SubprocessError.UnderlyingError(rawValue: GetLastError()))")
696696
}
697697
}

Sources/_SubprocessCShims/process_shims.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,12 +540,18 @@ int _subprocess_fork_exec(
540540
// If we reached this point, something went wrong
541541
write_error_and_exit;
542542
} else {
543+
#define reap_child_process_and_return_errno int capturedError = errno; \
544+
close(pipefd[0]); \
545+
siginfo_t info; \
546+
waitid(P_PID, childPid, &info, WEXITED); \
547+
return capturedError
548+
543549
// On Linux 5.3 and lower, we have to fetch pidfd separately
544550
// Newer Linux supports clone3 which returns pidfd directly
545551
if (_pidfd < 0) {
546552
_pidfd = _pidfd_open(childPid);
547553
if (_pidfd < 0) {
548-
return errno;
554+
reap_child_process_and_return_errno;
549555
}
550556
}
551557

@@ -555,8 +561,7 @@ int _subprocess_fork_exec(
555561
// Restore old signmask
556562
rc = pthread_sigmask(SIG_SETMASK, &old_sigmask, NULL);
557563
if (rc != 0) {
558-
close(pipefd[0]);
559-
return errno;
564+
reap_child_process_and_return_errno;
560565
}
561566

562567
// Unlock

0 commit comments

Comments
 (0)