From 21682acfae58003b673b9ccdd689a9abf116de71 Mon Sep 17 00:00:00 2001 From: Marshall Humble <11792578+marshallhumble@users.noreply.github.com> Date: Thu, 7 May 2026 19:39:27 -0500 Subject: [PATCH 1/3] bound the event channel to prevent unbounded RSS growth --- src/main.rs | 6 +++--- src/terminal.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index e8469d3..1466251 100644 --- a/src/main.rs +++ b/src/main.rs @@ -438,7 +438,7 @@ pub enum Message { TabNext, TabPrev, TermEvent(pane_grid::Pane, segmented_button::Entity, TermEvent), - TermEventTx(mpsc::UnboundedSender<(pane_grid::Pane, segmented_button::Entity, TermEvent)>), + TermEventTx(mpsc::Sender<(pane_grid::Pane, segmented_button::Entity, TermEvent)>), ToggleFullscreen, ToggleContextPage(ContextPage), UpdateDefaultProfile((bool, ProfileId)), @@ -503,7 +503,7 @@ pub struct App { find_search_id: widget::Id, find_search_value: String, term_event_tx_opt: - Option>, + Option>, startup_options: Option, term_config: term::Config, color_scheme_errors: Vec, @@ -3623,7 +3623,7 @@ impl Application for App { stream::channel( 100, |mut output: iced::futures::channel::mpsc::Sender| async move { - let (event_tx, mut event_rx) = mpsc::unbounded_channel(); + let (event_tx, mut event_rx) = mpsc::channel(1024); output.send(Message::TermEventTx(event_tx)).await.unwrap(); while let Some((pane, entity, event)) = event_rx.recv().await { diff --git a/src/terminal.rs b/src/terminal.rs index 81b9f50..d2b5efa 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -99,13 +99,13 @@ impl From for WindowSize { pub struct EventProxy( pane_grid::Pane, segmented_button::Entity, - mpsc::UnboundedSender<(pane_grid::Pane, segmented_button::Entity, Event)>, -); + mpsc::Sender<(pane_grid::Pane, segmented_button::Entity, Event)>, + ); impl EventListener for EventProxy { fn send_event(&self, event: Event) { //TODO: handle error - let _ = self.2.send((self.0, self.1, event)); + let _ = self.2.blocking_send((self.0, self.1, event)); } } @@ -270,7 +270,7 @@ impl Terminal { pub fn new( pane: pane_grid::Pane, entity: segmented_button::Entity, - event_tx: mpsc::UnboundedSender<(pane_grid::Pane, segmented_button::Entity, Event)>, + event_tx: mpsc::Sender<(pane_grid::Pane, segmented_button::Entity, Event)>, config: Config, options: Options, app_config: &AppConfig, From f16dc74a7ae3f8adb0720430f800cdf97a6bfb12 Mon Sep 17 00:00:00 2001 From: Jacob Kauffmann Date: Thu, 14 May 2026 15:39:59 -0600 Subject: [PATCH 2/3] chore: cargo fmt --- src/main.rs | 3 +-- src/terminal.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1466251..edee78d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -502,8 +502,7 @@ pub struct App { find: bool, find_search_id: widget::Id, find_search_value: String, - term_event_tx_opt: - Option>, + term_event_tx_opt: Option>, startup_options: Option, term_config: term::Config, color_scheme_errors: Vec, diff --git a/src/terminal.rs b/src/terminal.rs index d2b5efa..ecfb602 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -100,7 +100,7 @@ pub struct EventProxy( pane_grid::Pane, segmented_button::Entity, mpsc::Sender<(pane_grid::Pane, segmented_button::Entity, Event)>, - ); +); impl EventListener for EventProxy { fn send_event(&self, event: Event) { From ac436abac6d2ea0f0649acd615f817a8d577fcef Mon Sep 17 00:00:00 2001 From: Marshall Humble <11792578+marshallhumble@users.noreply.github.com> Date: Thu, 14 May 2026 17:29:31 -0500 Subject: [PATCH 3/3] docs: explain backpressure rationale for PTY event channel in --- src/main.rs | 4 ++++ src/terminal.rs | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index edee78d..231e967 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3622,6 +3622,10 @@ impl Application for App { stream::channel( 100, |mut output: iced::futures::channel::mpsc::Sender| async move { + // Bounded: when the GUI can't drain fast enough, alacritty's PTY reader + // blocks on send → kernel pipe fills → producing program is throttled by + // the OS. Capacity 1024 caps the queue depth; per-event memory depends on + // payload (Wakeup is ~100 B; Title/PtyWrite carry owned Strings). let (event_tx, mut event_rx) = mpsc::channel(1024); output.send(Message::TermEventTx(event_tx)).await.unwrap(); diff --git a/src/terminal.rs b/src/terminal.rs index ecfb602..8d8b469 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -104,7 +104,10 @@ pub struct EventProxy( impl EventListener for EventProxy { fn send_event(&self, event: Event) { - //TODO: handle error + // Bounded channel; blocking_send propagates backpressure to alacritty's + // PTY reader instead of letting events accumulate. Called from alacritty's + // std::thread PTY reader (not a tokio worker), so blocking is safe and + // blocking_send won't panic. let _ = self.2.blocking_send((self.0, self.1, event)); } }