-
Notifications
You must be signed in to change notification settings - Fork 0
Use atomic flag for SIGWINCH resize handling #1
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import ANSI | ||
| import Atomics | ||
| import Dispatch | ||
|
|
||
| #if canImport(Darwin) | ||
|
|
@@ -7,6 +8,9 @@ import Darwin | |
| import Glibc | ||
| #endif | ||
|
|
||
| /// Thread-safe flag for SIGWINCH signal (accessible from signal handler without actor isolation) | ||
| private let _resizeSignalReceived = ManagedAtomic<Bool>(false) | ||
|
|
||
| /// The central actor for terminal operations. | ||
| /// | ||
| /// `Terminal` provides thread-safe access to terminal capabilities including | ||
|
|
@@ -61,9 +65,6 @@ public actor Terminal { | |
| /// Signal source for SIGWINCH (terminal resize) | ||
| private var resizeSignalSource: DispatchSourceSignal? | ||
|
|
||
| /// Whether a resize event has occurred | ||
| public private(set) var resizeOccurred: Bool = false | ||
|
|
||
| // MARK: - Initialization | ||
|
|
||
| /// Create a new terminal instance with default configuration. | ||
|
|
@@ -418,12 +419,9 @@ public actor Terminal { | |
| // Create dispatch source for SIGWINCH | ||
| let source = DispatchSource.makeSignalSource(signal: SIGWINCH, queue: .main) | ||
| source.setEventHandler { | ||
| // Set a flag that can be checked in the event loop | ||
| // We can't safely call actor methods from here, so we just | ||
| // trigger the flag synchronously. The event loop will check it. | ||
| Task { @MainActor in | ||
| await Terminal.shared.handleResize() | ||
| } | ||
| // Set atomic flag directly - no Task needed | ||
| // This allows the flag to be set even when poll(2) is blocking | ||
| _resizeSignalReceived.store(true, ordering: .relaxed) | ||
|
||
| } | ||
| source.resume() | ||
| resizeSignalSource = source | ||
|
|
@@ -436,17 +434,15 @@ public actor Terminal { | |
| resizeSignalSource = nil | ||
| } | ||
|
|
||
| /// Handle a resize event. | ||
| private func handleResize() { | ||
| size = TerminalSize.detect(fd: outputFD) | ||
| resizeOccurred = true | ||
| } | ||
|
|
||
| /// Check and clear the resize flag. | ||
| /// Returns true if a resize occurred since last check. | ||
| public func checkResize() -> Bool { | ||
| let didResize = resizeOccurred | ||
| resizeOccurred = false | ||
| return didResize | ||
| // Atomically check and clear the flag | ||
| if _resizeSignalReceived.exchange(false, ordering: .relaxed) { | ||
|
||
| // Signal was received - refresh the terminal size | ||
| size = TerminalSize.detect(fd: outputFD) | ||
| return true | ||
| } | ||
| return false | ||
| } | ||
|
Comment on lines
437
to
447
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change from
terminal.sizetoterminal.refreshSize()is unnecessary for this demo. Thesizeproperty is already kept up-to-date bycheckResize()calls in the event loop. UsingrefreshSize()here forces an extra system call. Consider reverting toawait terminal.sizeunless there's a specific reason to force a refresh at this point.