Skip to content

Commit 12987a2

Browse files
Fix unbounded event buffer growth
The setup receiver outlived setup with a frozen index, pinning every subsequent event in the buffer for the App lifetime. Scope it to InstallTerminalInfo.
1 parent 7f80714 commit 12987a2

2 files changed

Lines changed: 7 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ Next
88
- Bugfix: `App::PostEvent` is now thread safe again, as documented. Since the
99
7.0.0 event loop rework it pushed into an unsynchronized buffer, racing with
1010
the main loop when called from another thread.
11+
- Bugfix: Fix unbounded memory growth in the event buffer. A receiver used
12+
during terminal setup was kept for the whole `App` lifetime, retaining every
13+
subsequent event (including every mouse move).
1114

1215
### Dom
1316
- Performance: `text` computes its requirement once and renders only the

src/ftxui/component/app.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ struct App::Internal {
245245
ThrottledRequest cursor_position_request;
246246

247247
MultiReceiverBuffer<Event> event_buffer;
248-
std::unique_ptr<MultiReceiverBuffer<Event>::Receiver> setup_receiver;
249248
std::unique_ptr<MultiReceiverBuffer<Event>::Receiver> main_loop_receiver;
250249

251250
Internal(App* app, AppDimension dimension, bool use_alternative_screen);
@@ -561,7 +560,6 @@ App::Internal::Internal(App* app,
561560
cursor_position_request(this, [this] {
562561
TerminalSend(DeviceStatusReport(DSRMode::kCursor));
563562
}) {
564-
setup_receiver = event_buffer.CreateReceiver();
565563
main_loop_receiver = event_buffer.CreateReceiver();
566564
}
567565

@@ -1182,6 +1180,10 @@ void App::Internal::InstallTerminalInfo() {
11821180

11831181
// Wait for the cursor shape reply using the setup head.
11841182
if (is_stdin_a_tty_ && is_stdout_a_tty_) {
1183+
// A receiver scoped to the setup: keeping one alive after setup would pin
1184+
// every subsequent event in the buffer, growing it for the whole app
1185+
// lifetime.
1186+
auto setup_receiver = event_buffer.CreateReceiver();
11851187
auto start = std::chrono::steady_clock::now();
11861188
bool terminal_capabilities_received = false;
11871189
// Wait for the cursor shape reply using the setup head.

0 commit comments

Comments
 (0)