Skip to content

Process: check for posix_spawn_file_actions_addchdir_np #4763

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion CoreFoundation/Base.subproj/CFPlatform.c
Original file line number Diff line number Diff line change
Expand Up @@ -2210,8 +2210,28 @@ CF_EXPORT int _CFPosixSpawnFileActionsAddClose(_CFPosixSpawnFileActionsRef file_
return posix_spawn_file_actions_addclose((posix_spawn_file_actions_t *)file_actions, filedes);
}

CF_EXPORT bool _CFPosixSpawnFileActionsAddChdirNPIsSupported() {
#if defined(__GLIBC__)
# if __GLIBC_PREREQ(2, 29)
return true;
# else
return false;
# endif
#else
return false;
#endif
}

CF_EXPORT int _CFPosixSpawnFileActionsAddChdirNP(_CFPosixSpawnFileActionsRef file_actions, const char *path) {
return posix_spawn_file_actions_addchdir_np((posix_spawn_file_actions_t *)file_actions, path);
#if defined(__GLIBC__)
# if __GLIBC_PREREQ(2, 29)
return posix_spawn_file_actions_addchdir_np((posix_spawn_file_actions_t *)file_actions, path);
# else
return ENOSYS;
# endif
#else
return ENOSYS;
#endif
}

CF_EXPORT int _CFPosixSpawn(pid_t *_CF_RESTRICT pid, const char *_CF_RESTRICT path, _CFPosixSpawnFileActionsRef file_actions, _CFPosixSpawnAttrRef _Nullable _CF_RESTRICT attrp, char *_Nullable const argv[_Nullable _CF_RESTRICT], char *_Nullable const envp[_Nullable _CF_RESTRICT]) {
Expand Down
1 change: 1 addition & 0 deletions CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@ CF_EXPORT int _CFPosixSpawn(pid_t *_CF_RESTRICT pid, const char *_CF_RESTRICT pa
#endif // __cplusplus

#if TARGET_OS_LINUX
CF_EXPORT bool _CFPosixSpawnFileActionsAddChdirNPIsSupported(void);
CF_EXPORT int _CFPosixSpawnFileActionsAddChdirNP(_CFPosixSpawnFileActionsRef file_actions, const char *path);
#endif // TARGET_OS_LINUX
#endif // !TARGET_OS_WIN32
Expand Down
53 changes: 45 additions & 8 deletions Sources/Foundation/Process.swift
Original file line number Diff line number Diff line change
Expand Up @@ -944,11 +944,38 @@ open class Process: NSObject {
}
#endif

#if os(Linux)
if let dir = currentDirectoryURL?.path {
#if os(Linux)
if let dir = currentDirectoryURL?.path, _CFPosixSpawnFileActionsAddChdirNPIsSupported() {
try _throwIfPosixError(_CFPosixSpawnFileActionsAddChdirNP(fileActions, dir))
} else {
try withCurrentDirectoryPath {
try posixLaunch(
launchPath: launchPath,
taskSocketPair: taskSocketPair,
fileActions: fileActions,
spawnAttrs: &spawnAttrs,
argv: argv,
envp: envp
)
}
}
#else
#else
try withCurrentDirectoryPath {
try posixLaunch(
launchPath: launchPath,
taskSocketPair: taskSocketPair,
fileActions: fileActions,
spawnAttrs: &spawnAttrs,
argv: argv,
envp: envp
)
}
#endif // os(Linux)
#endif // os(Windows)
}

#if !os(Windows)
private func withCurrentDirectoryPath(_ closure: () throws -> ()) throws {
// This is an unfortunate workaround: posix_spawn has no POSIX-specified way to set the working directory
// of the child process. glibc has a non-POSIX API option, which we use above. Here we take a brute-force
// approach of just changing our current working directory. This is not a great implementation and it's likely
Expand All @@ -965,14 +992,24 @@ open class Process: NSObject {
// Reset the previous working directory path.
fileManager.changeCurrentDirectoryPath(previousDirectoryPath)
}
#endif

try closure()
}

private func posixLaunch(
launchPath: String,
taskSocketPair: [Int32],
fileActions: _CFPosixSpawnFileActionsRef,
spawnAttrs: UnsafeMutablePointer<posix_spawnattr_t>,
argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>,
envp: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>
) throws {
// Launch
var pid = pid_t()
guard _CFPosixSpawn(&pid, launchPath, fileActions, &spawnAttrs, argv, envp) == 0 else {
guard _CFPosixSpawn(&pid, launchPath, fileActions, spawnAttrs, argv, envp) == 0 else {
throw _NSErrorWithErrno(errno, reading: true, path: launchPath)
}
posix_spawnattr_destroy(&spawnAttrs)
posix_spawnattr_destroy(spawnAttrs)

// Close the write end of the input and output pipes.
if let pipe = standardInput as? Pipe {
Expand Down Expand Up @@ -1004,9 +1041,9 @@ open class Process: NSObject {
isRunning = true

self.processIdentifier = pid
#endif
}

#endif

open func interrupt() {
precondition(hasStarted, "task not launched")
#if os(Windows)
Expand Down