From fddda82649f8eff684c677ceea02b4e03f9e558e Mon Sep 17 00:00:00 2001 From: Michael Chiu Date: Sun, 8 Dec 2024 19:15:13 -0800 Subject: [PATCH 1/2] Fix FreeBSD build Various fixes to enable building on FreeBSD. Fixed an issue that warning messages from libthr can be emitted to stderr when thread specific data is used. This is due to CoreFoundation setting the TSD to `CF_TSD_BAD_PTR` even after `PTHERAD_DESTRUCTOR_ITERATIONS` iterators of dtor calls. This causes libthr to emit a warning to stderr about left-over non-null TSD after max destructor iterations. --- Sources/CoreFoundation/CFPlatform.c | 8 ++++++-- Sources/CoreFoundation/include/CoreFoundation.h | 2 +- .../internalInclude/CFBundle_Internal.h | 2 +- Sources/Foundation/FileManager+POSIX.swift | 2 +- Sources/Foundation/FileManager.swift | 8 +++++++- Sources/Foundation/Host.swift | 6 +++--- Sources/Foundation/NSLock.swift | 6 +++--- Sources/Foundation/NSPlatform.swift | 2 +- Sources/Foundation/Port.swift | 4 ++-- Sources/Foundation/Process.swift | 4 ++-- Sources/Foundation/Thread.swift | 13 ++++++++++--- 11 files changed, 37 insertions(+), 20 deletions(-) diff --git a/Sources/CoreFoundation/CFPlatform.c b/Sources/CoreFoundation/CFPlatform.c index 83fbfd7743..d9c4d5b6be 100644 --- a/Sources/CoreFoundation/CFPlatform.c +++ b/Sources/CoreFoundation/CFPlatform.c @@ -281,7 +281,7 @@ const char *_CFProcessPath(void) { #if TARGET_OS_MAC || TARGET_OS_WIN32 || TARGET_OS_BSD CF_CROSS_PLATFORM_EXPORT Boolean _CFIsMainThread(void) { -#if defined(__OpenBSD__) +#if defined(__OpenBSD__) || defined(__FreeBSD__) return pthread_equal(pthread_self(), _CFMainPThread) != 0; #else return pthread_main_np() == 1; @@ -928,9 +928,13 @@ static void __CFTSDFinalize(void *arg) { #if _POSIX_THREADS && !TARGET_OS_WASI if (table->destructorCount == PTHREAD_DESTRUCTOR_ITERATIONS - 1) { // On PTHREAD_DESTRUCTOR_ITERATIONS-1 call, destroy our data free(table); - + + // FreeBSD libthr emits debug message to stderr if there are leftover nonnull TSD after PTHREAD_DESTRUCTOR_ITERATIONS + // On this platform, the destructor will never be called again, therefore it is unneccessary to set the TSD to CF_TSD_BAD_PTR + #if !defined(FreeBSD) // Now if the destructor is called again we will take the shortcut at the beginning of this function. __CFTSDSetSpecific(CF_TSD_BAD_PTR); + #endif return; } #else diff --git a/Sources/CoreFoundation/include/CoreFoundation.h b/Sources/CoreFoundation/include/CoreFoundation.h index 64313f0b9f..027f067df3 100644 --- a/Sources/CoreFoundation/include/CoreFoundation.h +++ b/Sources/CoreFoundation/include/CoreFoundation.h @@ -74,7 +74,7 @@ #include "ForSwiftFoundationOnly.h" -#if TARGET_OS_OSX || TARGET_OS_IPHONE || TARGET_OS_WIN32 || TARGET_OS_LINUX || TARGET_OS_WASI +#if TARGET_OS_OSX || TARGET_OS_IPHONE || TARGET_OS_WIN32 || TARGET_OS_LINUX || TARGET_OS_WASI || TARGET_OS_BSD # if !TARGET_OS_WASI #include "CFMessagePort.h" #include "CFPlugIn.h" diff --git a/Sources/CoreFoundation/internalInclude/CFBundle_Internal.h b/Sources/CoreFoundation/internalInclude/CFBundle_Internal.h index 265e65de09..b087fca188 100644 --- a/Sources/CoreFoundation/internalInclude/CFBundle_Internal.h +++ b/Sources/CoreFoundation/internalInclude/CFBundle_Internal.h @@ -431,7 +431,7 @@ CF_PRIVATE const CFStringRef _kCFBundleUseAppleLocalizationsKey; // The buffer must be PATH_MAX long or more. static bool _CFGetPathFromFileDescriptor(int fd, char *path); -#if TARGET_OS_MAC || (TARGET_OS_BSD && !defined(__OpenBSD__)) +#if TARGET_OS_MAC || (TARGET_OS_BSD && !defined(__OpenBSD__) && !defined(__FreeBSD__)) static bool _CFGetPathFromFileDescriptor(int fd, char *path) { return fcntl(fd, F_GETPATH, path) != -1; diff --git a/Sources/Foundation/FileManager+POSIX.swift b/Sources/Foundation/FileManager+POSIX.swift index 845ca89221..e2fd67290c 100644 --- a/Sources/Foundation/FileManager+POSIX.swift +++ b/Sources/Foundation/FileManager+POSIX.swift @@ -89,7 +89,7 @@ extension FileManager { } urls = mountPoints(statBuf, Int(fsCount)) } -#elseif os(OpenBSD) +#elseif os(OpenBSD) || os(FreeBSD) func mountPoints(_ statBufs: UnsafePointer, _ fsCount: Int) -> [URL] { var urls: [URL] = [] diff --git a/Sources/Foundation/FileManager.swift b/Sources/Foundation/FileManager.swift index 5a68934853..2349717661 100644 --- a/Sources/Foundation/FileManager.swift +++ b/Sources/Foundation/FileManager.swift @@ -316,9 +316,15 @@ extension FileManager { flags |= flagsToSet flags &= ~flagsToUnset - guard chflags(fsRep, flags) == 0 else { +#if os(FreeBSD) + guard chflags(path, UInt(flags)) == 0 else { throw _NSErrorWithErrno(errno, reading: false, path: path) } +#else + guard chflags(path, flags) == 0 else { + throw _NSErrorWithErrno(errno, reading: false, path: path) + } +#endif #endif } diff --git a/Sources/Foundation/Host.swift b/Sources/Foundation/Host.swift index 6c4f5291f6..d6c32760c3 100644 --- a/Sources/Foundation/Host.swift +++ b/Sources/Foundation/Host.swift @@ -194,7 +194,7 @@ open class Host: NSObject { let family = ifa_addr.pointee.sa_family if family == sa_family_t(AF_INET) || family == sa_family_t(AF_INET6) { let sa_len: socklen_t = socklen_t((family == sa_family_t(AF_INET6)) ? MemoryLayout.size : MemoryLayout.size) -#if os(OpenBSD) +#if os(OpenBSD) || os(FreeBSD) let hostlen = size_t(NI_MAXHOST) #else let hostlen = socklen_t(NI_MAXHOST) @@ -294,7 +294,7 @@ open class Host: NSObject { } var hints = addrinfo() hints.ai_family = PF_UNSPEC -#if os(macOS) || os(iOS) || os(Android) || os(OpenBSD) || canImport(Musl) +#if os(macOS) || os(iOS) || os(Android) || os(OpenBSD) || canImport(Musl) || os(FreeBSD) hints.ai_socktype = SOCK_STREAM #else hints.ai_socktype = Int32(SOCK_STREAM.rawValue) @@ -324,7 +324,7 @@ open class Host: NSObject { } let sa_len: socklen_t = socklen_t((family == AF_INET6) ? MemoryLayout.size : MemoryLayout.size) let lookupInfo = { (content: inout [String], flags: Int32) in -#if os(OpenBSD) +#if os(OpenBSD) || os(FreeBSD) let hostlen = size_t(NI_MAXHOST) #else let hostlen = socklen_t(NI_MAXHOST) diff --git a/Sources/Foundation/NSLock.swift b/Sources/Foundation/NSLock.swift index fe1d08b775..6ea390f109 100644 --- a/Sources/Foundation/NSLock.swift +++ b/Sources/Foundation/NSLock.swift @@ -39,7 +39,7 @@ extension NSLocking { private typealias _MutexPointer = UnsafeMutablePointer private typealias _RecursiveMutexPointer = UnsafeMutablePointer private typealias _ConditionVariablePointer = UnsafeMutablePointer -#elseif CYGWIN || os(OpenBSD) +#elseif CYGWIN || os(OpenBSD) || os(FreeBSD) private typealias _MutexPointer = UnsafeMutablePointer private typealias _RecursiveMutexPointer = UnsafeMutablePointer private typealias _ConditionVariablePointer = UnsafeMutablePointer @@ -287,14 +287,14 @@ open class NSRecursiveLock: NSObject, NSLocking, @unchecked Sendable { InitializeConditionVariable(timeoutCond) InitializeSRWLock(timeoutMutex) #else -#if CYGWIN || os(OpenBSD) +#if CYGWIN || os(OpenBSD) || os(FreeBSD) var attrib : pthread_mutexattr_t? = nil #else var attrib = pthread_mutexattr_t() #endif withUnsafeMutablePointer(to: &attrib) { attrs in pthread_mutexattr_init(attrs) -#if os(OpenBSD) +#if os(OpenBSD) || os(FreeBSD) let type = Int32(PTHREAD_MUTEX_RECURSIVE.rawValue) #else let type = Int32(PTHREAD_MUTEX_RECURSIVE) diff --git a/Sources/Foundation/NSPlatform.swift b/Sources/Foundation/NSPlatform.swift index a18090265d..4b63904252 100644 --- a/Sources/Foundation/NSPlatform.swift +++ b/Sources/Foundation/NSPlatform.swift @@ -9,7 +9,7 @@ #if os(macOS) || os(iOS) fileprivate let _NSPageSize = Int(vm_page_size) -#elseif os(Linux) || os(Android) || os(OpenBSD) +#elseif os(Linux) || os(Android) || os(OpenBSD) || os(FreeBSD) fileprivate let _NSPageSize = Int(getpagesize()) #elseif os(Windows) import WinSDK diff --git a/Sources/Foundation/Port.swift b/Sources/Foundation/Port.swift index acef3c9960..39dbaf1fd5 100644 --- a/Sources/Foundation/Port.swift +++ b/Sources/Foundation/Port.swift @@ -107,7 +107,7 @@ fileprivate let FOUNDATION_SOCK_STREAM = SOCK_STREAM fileprivate let FOUNDATION_IPPROTO_TCP = IPPROTO_TCP #endif -#if canImport(Glibc) && !os(Android) && !os(OpenBSD) +#if canImport(Glibc) && !os(Android) && !os(OpenBSD) && !os(FreeBSD) import Glibc fileprivate let FOUNDATION_SOCK_STREAM = Int32(SOCK_STREAM.rawValue) fileprivate let FOUNDATION_IPPROTO_TCP = Int32(IPPROTO_TCP) @@ -119,7 +119,7 @@ fileprivate let FOUNDATION_SOCK_STREAM = Int32(SOCK_STREAM) fileprivate let FOUNDATION_IPPROTO_TCP = Int32(IPPROTO_TCP) #endif -#if canImport(Glibc) && os(Android) || os(OpenBSD) +#if canImport(Glibc) && os(Android) || os(OpenBSD) || os(FreeBSD) import Glibc fileprivate let FOUNDATION_SOCK_STREAM = Int32(SOCK_STREAM) fileprivate let FOUNDATION_IPPROTO_TCP = Int32(IPPROTO_TCP) diff --git a/Sources/Foundation/Process.swift b/Sources/Foundation/Process.swift index 758dd1dfd4..81ab9ab610 100644 --- a/Sources/Foundation/Process.swift +++ b/Sources/Foundation/Process.swift @@ -779,7 +779,7 @@ open class Process: NSObject, @unchecked Sendable { } var taskSocketPair : [Int32] = [0, 0] -#if os(macOS) || os(iOS) || os(Android) || os(OpenBSD) || canImport(Musl) +#if os(macOS) || os(iOS) || os(Android) || os(OpenBSD) || os(FreeBSD) || canImport(Musl) socketpair(AF_UNIX, SOCK_STREAM, 0, &taskSocketPair) #else socketpair(AF_UNIX, Int32(SOCK_STREAM.rawValue), 0, &taskSocketPair) @@ -936,7 +936,7 @@ open class Process: NSObject, @unchecked Sendable { useFallbackChdir = false } -#if canImport(Darwin) || os(Android) || os(OpenBSD) +#if canImport(Darwin) || os(Android) || os(OpenBSD) || os(FreeBSD) var spawnAttrs: posix_spawnattr_t? = nil #else var spawnAttrs: posix_spawnattr_t = posix_spawnattr_t() diff --git a/Sources/Foundation/Thread.swift b/Sources/Foundation/Thread.swift index 5e79579c62..5a9a2a94f4 100644 --- a/Sources/Foundation/Thread.swift +++ b/Sources/Foundation/Thread.swift @@ -224,7 +224,7 @@ open class Thread : NSObject { get { _attrStorage.value } set { _attrStorage.value = newValue } } -#elseif CYGWIN || os(OpenBSD) +#elseif CYGWIN || os(OpenBSD) || os(FreeBSD) internal var _attr : pthread_attr_t? = nil #else internal var _attr = pthread_attr_t() @@ -264,7 +264,7 @@ open class Thread : NSObject { _status = .finished return } -#if CYGWIN || os(OpenBSD) +#if CYGWIN || os(OpenBSD) || os(FreeBSD) if let attr = self._attr { _thread = self.withRetainedReference { return _CFThreadCreate(attr, NSThreadStart, $0) @@ -388,6 +388,8 @@ open class Thread : NSObject { #elseif os(Windows) let count = RtlCaptureStackBackTrace(0, DWORD(maxSupportedStackDepth), addrs, nil) +#elseif os(FreeBSD) + let count = backtrace(addrs, maxSupportedStackDepth) #else let count = backtrace(addrs, Int32(maxSupportedStackDepth)) #endif @@ -449,7 +451,12 @@ open class Thread : NSObject { #else return backtraceAddresses({ (addrs, count) in var symbols: [String] = [] - if let bs = backtrace_symbols(addrs, Int32(count)) { +#if os(FreeBSD) + let bs = backtrace_symbols(addrs, count) +#else + let bs = backtrace_symbols(addrs, Int32(count)) +#endif + if let bs { symbols = UnsafeBufferPointer(start: bs, count: count).map { guard let symbol = $0 else { return "" From fef99303c8e2728028a863b4cb51fc218a7d64c8 Mon Sep 17 00:00:00 2001 From: Michael Chiu Date: Sun, 8 Dec 2024 22:13:34 -0800 Subject: [PATCH 2/2] typo --- Sources/CoreFoundation/CFPlatform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CoreFoundation/CFPlatform.c b/Sources/CoreFoundation/CFPlatform.c index d9c4d5b6be..8a6e2adf4f 100644 --- a/Sources/CoreFoundation/CFPlatform.c +++ b/Sources/CoreFoundation/CFPlatform.c @@ -931,7 +931,7 @@ static void __CFTSDFinalize(void *arg) { // FreeBSD libthr emits debug message to stderr if there are leftover nonnull TSD after PTHREAD_DESTRUCTOR_ITERATIONS // On this platform, the destructor will never be called again, therefore it is unneccessary to set the TSD to CF_TSD_BAD_PTR - #if !defined(FreeBSD) + #if !defined(__FreeBSD__) // Now if the destructor is called again we will take the shortcut at the beginning of this function. __CFTSDSetSpecific(CF_TSD_BAD_PTR); #endif