Skip to content
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

Add a thread-safe implementation of Process.currentDirectoryURL #4981

Merged
merged 1 commit into from
Sep 26, 2024
Merged
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
29 changes: 29 additions & 0 deletions Sources/CoreFoundation/CFPlatform.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
#define kCFPlatformInterfaceStringEncoding CFStringGetSystemEncoding()
#endif

#ifndef __GLIBC_PREREQ
#define __GLIBC_PREREQ(maj, min) 0
#endif

extern void __CFGetUGIDs(uid_t *euid, gid_t *egid);

#if TARGET_OS_MAC
Expand Down Expand Up @@ -2274,6 +2278,31 @@ CF_EXPORT int _CFPosixSpawnFileActionsAddClose(_CFPosixSpawnFileActionsRef file_
return posix_spawn_file_actions_addclose((posix_spawn_file_actions_t *)file_actions, filedes);
}

CF_EXPORT int _CFPosixSpawnFileActionsChdir(_CFPosixSpawnFileActionsRef file_actions, const char *path) {
#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 29)
// Glibc versions prior to 2.29 don't support posix_spawn_file_actions_addchdir_np, impacting:
// - Amazon Linux 2 (EoL mid-2025)
return ENOSYS;
#elif defined(__GLIBC__) || TARGET_OS_DARWIN || defined(__FreeBSD__) || defined(__ANDROID__)
// Pre-standard posix_spawn_file_actions_addchdir_np version available in:
// - Solaris 11.3 (October 2015)
// - Glibc 2.29 (February 2019)
// - macOS 10.15 (October 2019)
// - musl 1.1.24 (October 2019)
// - FreeBSD 13.1 (May 2022)
// - Android 14 (October 2023)
return posix_spawn_file_actions_addchdir_np((posix_spawn_file_actions_t *)file_actions, path);
#else
// Standardized posix_spawn_file_actions_addchdir version (POSIX.1-2024, June 2024) available in:
// - Solaris 11.4 (August 2018)
// - NetBSD 10.0 (March 2024)
// Currently missing as of:
// - OpenBSD 7.5 (April 2024)
// - QNX 8 (December 2023)
return posix_spawn_file_actions_addchdir((posix_spawn_file_actions_t *)file_actions, path);
#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]) {
return posix_spawn(pid, path, (posix_spawn_file_actions_t *)file_actions, (posix_spawnattr_t *)attrp, argv, envp);
}
Expand Down
1 change: 1 addition & 0 deletions Sources/CoreFoundation/include/ForSwiftFoundationOnly.h
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,7 @@ CF_EXPORT int _CFPosixSpawnFileActionsDestroy(_CFPosixSpawnFileActionsRef file_a
CF_EXPORT void _CFPosixSpawnFileActionsDealloc(_CFPosixSpawnFileActionsRef file_actions);
CF_EXPORT int _CFPosixSpawnFileActionsAddDup2(_CFPosixSpawnFileActionsRef file_actions, int filedes, int newfiledes);
CF_EXPORT int _CFPosixSpawnFileActionsAddClose(_CFPosixSpawnFileActionsRef file_actions, int filedes);
CF_EXPORT int _CFPosixSpawnFileActionsChdir(_CFPosixSpawnFileActionsRef file_actions, const char *path);
#ifdef __cplusplus
CF_EXPORT int _CFPosixSpawn(pid_t *_CF_RESTRICT pid, const char *_CF_RESTRICT path, _CFPosixSpawnFileActionsRef file_actions, _CFPosixSpawnAttrRef _Nullable _CF_RESTRICT attrp, char *const argv[], char *const envp[]);
#else
Expand Down
14 changes: 3 additions & 11 deletions Sources/Foundation/Process.swift
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,9 @@ open class Process: NSObject, @unchecked Sendable {
for fd in addclose.filter({ $0 >= 0 }) {
try _throwIfPosixError(_CFPosixSpawnFileActionsAddClose(fileActions, fd))
}
if let dir = currentDirectoryURL?.path {
try _throwIfPosixError(_CFPosixSpawnFileActionsChdir(fileActions, dir))
}

#if canImport(Darwin) || os(Android) || os(OpenBSD)
var spawnAttrs: posix_spawnattr_t? = nil
Expand All @@ -947,17 +950,6 @@ open class Process: NSObject, @unchecked Sendable {
}
#endif

let fileManager = FileManager()
let previousDirectoryPath = fileManager.currentDirectoryPath
if let dir = currentDirectoryURL?.path, !fileManager.changeCurrentDirectoryPath(dir) {
throw _NSErrorWithErrno(errno, reading: true, url: currentDirectoryURL)
}

defer {
// Reset the previous working directory path.
_ = fileManager.changeCurrentDirectoryPath(previousDirectoryPath)
}

// Launch
var pid = pid_t()

Expand Down