diff --git a/Sources/Testing/ExitTests/ExitTest.swift b/Sources/Testing/ExitTests/ExitTest.swift index f21104f3..73d78d9b 100644 --- a/Sources/Testing/ExitTests/ExitTest.swift +++ b/Sources/Testing/ExitTests/ExitTest.swift @@ -114,7 +114,7 @@ extension ExitTest { // As with Linux, disable the generation core files. FreeBSD does not, as // far as I can tell, special-case RLIMIT_CORE=1. var rl = rlimit(rlim_cur: 0, rlim_max: 0) - _ = setrlimit(CInt(RLIMIT_CORE.rawValue), &rl) + _ = setrlimit(RLIMIT_CORE, &rl) #elseif os(Windows) // On Windows, similarly disable Windows Error Reporting and the Windows // Error Reporting UI. Note we expect to be the first component to call diff --git a/Sources/Testing/ExitTests/SpawnProcess.swift b/Sources/Testing/ExitTests/SpawnProcess.swift index 7dd845c6..e58584be 100644 --- a/Sources/Testing/ExitTests/SpawnProcess.swift +++ b/Sources/Testing/ExitTests/SpawnProcess.swift @@ -143,12 +143,19 @@ func spawnExecutable( #if SWT_TARGET_OS_APPLE // Close all other file descriptors open in the parent. flags |= CShort(POSIX_SPAWN_CLOEXEC_DEFAULT) -#elseif os(Linux) || os(FreeBSD) +#elseif os(Linux) // This platform doesn't have POSIX_SPAWN_CLOEXEC_DEFAULT, but we can at // least close all file descriptors higher than the highest inherited one. // We are assuming here that the caller didn't set FD_CLOEXEC on any of // these file descriptors. _ = swt_posix_spawn_file_actions_addclosefrom_np(fileActions, highestFD + 1) +#elseif os(FreeBSD) + // Like Linux, this platfrom doesn't have POSIX_SPAWN_CLOEXEC_DEFAULT; + // However; unlike Linux, all non-EOL FreeBSD (>= 13.1) supports + // `posix_spawn_file_actions_addclosefrom_np` and therefore we don't need + // need `swt_posix_spawn_file_actions_addclosefrom_np` to guard the availability + // of this api. + _ = posix_spawn_file_actions_addclosefrom_np(fileActions, highestFD + 1) #else #warning("Platform-specific implementation missing: cannot close unused file descriptors") #endif diff --git a/Sources/Testing/ExitTests/WaitFor.swift b/Sources/Testing/ExitTests/WaitFor.swift index 521a092d..287e26e4 100644 --- a/Sources/Testing/ExitTests/WaitFor.swift +++ b/Sources/Testing/ExitTests/WaitFor.swift @@ -85,7 +85,11 @@ private let _childProcessContinuations = Locked<[pid_t: CheckedContinuation.allocate(capacity: 1) + #else let result = UnsafeMutablePointer.allocate(capacity: 1) + #endif _ = pthread_cond_init(result, nil) return result }() @@ -132,7 +136,7 @@ private let _createWaitThread: Void = { // Create the thread. It will run immediately; because it runs in an infinite // loop, we aren't worried about detaching or joining it. -#if SWT_TARGET_OS_APPLE +#if SWT_TARGET_OS_APPLE || os(FreeBSD) var thread: pthread_t? #else var thread = pthread_t() diff --git a/Sources/Testing/Support/Locked.swift b/Sources/Testing/Support/Locked.swift index df18319d..61013cd3 100644 --- a/Sources/Testing/Support/Locked.swift +++ b/Sources/Testing/Support/Locked.swift @@ -36,20 +36,22 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { /// To keep the implementation of this type as simple as possible, /// `pthread_mutex_t` is used on Apple platforms instead of `os_unfair_lock` /// or `OSAllocatedUnfairLock`. -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded)) - private typealias _Lock = pthread_mutex_t +#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded)) + typealias PlatformLock = pthread_mutex_t +#elseif os(FreeBSD) + typealias PlatformLock = pthread_mutex_t? #elseif os(Windows) - private typealias _Lock = SRWLOCK + typealias PlatformLock = SRWLOCK #elseif os(WASI) // No locks on WASI without multithreaded runtime. - private typealias _Lock = Void + typealias PlatformLock = Void #else #warning("Platform-specific implementation missing: locking unavailable") - private typealias _Lock = Void + typealias PlatformLock = Void #endif /// A type providing heap-allocated storage for an instance of ``Locked``. - private final class _Storage: ManagedBuffer { + private final class _Storage: ManagedBuffer { deinit { withUnsafeMutablePointerToElements { lock in #if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded)) @@ -66,7 +68,7 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { } /// Storage for the underlying lock and wrapped value. - private nonisolated(unsafe) var _storage: ManagedBuffer + private nonisolated(unsafe) var _storage: ManagedBuffer init(rawValue: T) { _storage = _Storage.create(minimumCapacity: 1, makingHeaderWith: { _ in rawValue }) @@ -142,7 +144,7 @@ struct Locked: RawRepresentable, Sendable where T: Sendable { /// - Warning: Callers that unlock the lock _must_ lock it again before the /// closure returns. If the lock is not acquired when `body` returns, the /// effect is undefined. - nonmutating func withUnsafeUnderlyingLock(_ body: (UnsafeMutablePointer, T) throws -> R) rethrows -> R { + nonmutating func withUnsafeUnderlyingLock(_ body: (UnsafeMutablePointer, T) throws -> R) rethrows -> R { try withLock { value in try _storage.withUnsafeMutablePointerToElements { lock in try body(lock, value) diff --git a/Sources/_TestingInternals/include/Includes.h b/Sources/_TestingInternals/include/Includes.h index 4a621d5c..51c02e27 100644 --- a/Sources/_TestingInternals/include/Includes.h +++ b/Sources/_TestingInternals/include/Includes.h @@ -80,6 +80,10 @@ #include #endif +#if __has_include() +#include +#endif + #if __has_include() #include #endif @@ -125,6 +129,10 @@ #endif #endif +#if defined(__FreeBSD__) +#include +#endif + #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #define NOMINMAX