Compare commits

..

1 Commits

Author SHA1 Message Date
Max Goedjen
bb0b6d8dc3 Run filehandle listening methods in main actor directly vs jumping (#765) 2025-11-27 20:00:53 +00:00
4 changed files with 31 additions and 25 deletions

View File

@@ -25,8 +25,8 @@ jobs:
- language: actions - language: actions
build-mode: none build-mode: none
# Disable this until CodeQL supports Xcode 26 builds. # Disable this until CodeQL supports Xcode 26 builds.
- language: swift # - language: swift
build-mode: manual # build-mode: manual
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4

View File

@@ -36,16 +36,16 @@ public struct SocketController {
logger.debug("Socket controller path is clear") logger.debug("Socket controller path is clear")
port = SocketPort(path: path) port = SocketPort(path: path)
fileHandle = FileHandle(fileDescriptor: port.socket, closeOnDealloc: true) fileHandle = FileHandle(fileDescriptor: port.socket, closeOnDealloc: true)
Task { [fileHandle, sessionsContinuation, logger] in Task { @MainActor [fileHandle, sessionsContinuation, logger] in
for await notification in NotificationCenter.default.notifications(named: .NSFileHandleConnectionAccepted) { for await notification in NotificationCenter.default.notifications(named: .NSFileHandleConnectionAccepted) {
logger.debug("Socket controller accepted connection") logger.debug("Socket controller accepted connection")
guard let new = notification.userInfo?[NSFileHandleNotificationFileHandleItem] as? FileHandle else { continue } guard let new = notification.userInfo?[NSFileHandleNotificationFileHandleItem] as? FileHandle else { continue }
let session = Session(fileHandle: new) let session = Session(fileHandle: new)
sessionsContinuation.yield(session) sessionsContinuation.yield(session)
await fileHandle.acceptConnectionInBackgroundAndNotifyOnMainActor() fileHandle.acceptConnectionInBackgroundAndNotify()
} }
} }
fileHandle.acceptConnectionInBackgroundAndNotify(forModes: [RunLoop.Mode.common]) fileHandle.acceptConnectionInBackgroundAndNotify()
logger.debug("Socket listening at \(path)") logger.debug("Socket listening at \(path)")
} }
@@ -90,16 +90,16 @@ extension SocketController {
logger.debug("Socket controller yielded data.") logger.debug("Socket controller yielded data.")
} }
} }
Task { fileHandle.waitForDataInBackgroundAndNotify()
await fileHandle.waitForDataInBackgroundAndNotifyOnMainActor()
}
} }
/// Writes new data to the socket. /// Writes new data to the socket.
/// - Parameter data: The data to write. /// - Parameter data: The data to write.
public func write(_ data: Data) async throws { public func write(_ data: Data) async throws {
try fileHandle.write(contentsOf: data) try fileHandle.write(contentsOf: data)
await fileHandle.waitForDataInBackgroundAndNotifyOnMainActor() await MainActor.run {
fileHandle.waitForDataInBackgroundAndNotify()
}
} }
/// Closes the socket and cleans up resources. /// Closes the socket and cleans up resources.
@@ -113,22 +113,6 @@ extension SocketController {
} }
private extension FileHandle {
/// Ensures waitForDataInBackgroundAndNotify will be called on the main actor.
@MainActor func waitForDataInBackgroundAndNotifyOnMainActor() {
waitForDataInBackgroundAndNotify()
}
/// Ensures acceptConnectionInBackgroundAndNotify will be called on the main actor.
/// - Parameter modes: the runloop modes to use.
@MainActor func acceptConnectionInBackgroundAndNotifyOnMainActor(forModes modes: [RunLoop.Mode]? = [RunLoop.Mode.common]) {
acceptConnectionInBackgroundAndNotify(forModes: modes)
}
}
private extension SocketPort { private extension SocketPort {
convenience init(path: String) { convenience init(path: String) {

View File

@@ -830,6 +830,8 @@
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -904,7 +906,9 @@
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -945,9 +949,11 @@
DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6; DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = YES;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO; ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO; ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
@@ -983,9 +989,11 @@
DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6; DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = YES;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO; ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO; ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
@@ -1266,6 +1274,8 @@
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -1312,9 +1322,11 @@
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\"";
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = YES;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = NO; ENABLE_HARDENED_RUNTIME = NO;
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO; ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO; ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;

View File

@@ -2,6 +2,16 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.security.hardened-process</key>
<true/>
<key>com.apple.security.hardened-process.dyld-ro</key>
<true/>
<key>com.apple.security.hardened-process.enhanced-security-version</key>
<integer>1</integer>
<key>com.apple.security.hardened-process.hardened-heap</key>
<true/>
<key>com.apple.security.hardened-process.platform-restrictions</key>
<integer>2</integer>
<key>com.apple.security.smartcard</key> <key>com.apple.security.smartcard</key>
<true/> <true/>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>