mirror of
https://github.com/openai/codex.git
synced 2026-04-24 22:54:54 +00:00
14 KiB
14 KiB
PR #1683: fix: crash on resize
- URL: https://github.com/openai/codex/pull/1683
- Author: nornagon-openai
- Created: 2025-07-25 20:47:32 UTC
- Updated: 2025-07-25 21:23:45 UTC
- Changes: +44/-32, Files changed: 1, Commits: 2
Description
Without this, resizing the terminal prints "Error: The cursor position could not be read within a normal duration" and quits the app.
Full Diff
diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs
index 4e2133a6be..e7097e6af0 100644
--- a/codex-rs/tui/src/app.rs
+++ b/codex-rs/tui/src/app.rs
@@ -88,39 +88,51 @@ impl App<'_> {
{
let app_event_tx = app_event_tx.clone();
std::thread::spawn(move || {
- while let Ok(event) = crossterm::event::read() {
- match event {
- crossterm::event::Event::Key(key_event) => {
- app_event_tx.send(AppEvent::KeyEvent(key_event));
- }
- crossterm::event::Event::Resize(_, _) => {
- app_event_tx.send(AppEvent::RequestRedraw);
- }
- crossterm::event::Event::Mouse(MouseEvent {
- kind: MouseEventKind::ScrollUp,
- ..
- }) => {
- scroll_event_helper.scroll_up();
- }
- crossterm::event::Event::Mouse(MouseEvent {
- kind: MouseEventKind::ScrollDown,
- ..
- }) => {
- scroll_event_helper.scroll_down();
- }
- crossterm::event::Event::Paste(pasted) => {
- // Many terminals convert newlines to \r when
- // pasting, e.g. [iTerm2][]. But [tui-textarea
- // expects \n][tui-textarea]. This seems like a bug
- // in tui-textarea IMO, but work around it for now.
- // [tui-textarea]: https://github.com/rhysd/tui-textarea/blob/4d18622eeac13b309e0ff6a55a46ac6706da68cf/src/textarea.rs#L782-L783
- // [iTerm2]: https://github.com/gnachman/iTerm2/blob/5d0c0d9f68523cbd0494dad5422998964a2ecd8d/sources/iTermPasteHelper.m#L206-L216
- let pasted = pasted.replace("\r", "\n");
- app_event_tx.send(AppEvent::Paste(pasted));
- }
- _ => {
- // Ignore any other events.
+ loop {
+ // This timeout is necessary to avoid holding the event lock
+ // that crossterm::event::read() acquires. In particular,
+ // reading the cursor position (crossterm::cursor::position())
+ // needs to acquire the event lock, and so will fail if it
+ // can't acquire it within 2 sec. Resizing the terminal
+ // crashes the app if the cursor position can't be read.
+ if let Ok(true) = crossterm::event::poll(Duration::from_millis(100)) {
+ if let Ok(event) = crossterm::event::read() {
+ match event {
+ crossterm::event::Event::Key(key_event) => {
+ app_event_tx.send(AppEvent::KeyEvent(key_event));
+ }
+ crossterm::event::Event::Resize(_, _) => {
+ app_event_tx.send(AppEvent::RequestRedraw);
+ }
+ crossterm::event::Event::Mouse(MouseEvent {
+ kind: MouseEventKind::ScrollUp,
+ ..
+ }) => {
+ scroll_event_helper.scroll_up();
+ }
+ crossterm::event::Event::Mouse(MouseEvent {
+ kind: MouseEventKind::ScrollDown,
+ ..
+ }) => {
+ scroll_event_helper.scroll_down();
+ }
+ crossterm::event::Event::Paste(pasted) => {
+ // Many terminals convert newlines to \r when
+ // pasting, e.g. [iTerm2][]. But [tui-textarea
+ // expects \n][tui-textarea]. This seems like a bug
+ // in tui-textarea IMO, but work around it for now.
+ // [tui-textarea]: https://github.com/rhysd/tui-textarea/blob/4d18622eeac13b309e0ff6a55a46ac6706da68cf/src/textarea.rs#L782-L783
+ // [iTerm2]: https://github.com/gnachman/iTerm2/blob/5d0c0d9f68523cbd0494dad5422998964a2ecd8d/sources/iTermPasteHelper.m#L206-L216
+ let pasted = pasted.replace("\r", "\n");
+ app_event_tx.send(AppEvent::Paste(pasted));
+ }
+ _ => {
+ // Ignore any other events.
+ }
+ }
}
+ } else {
+ // Timeout expired, no `Event` is available
}
}
});
Review Comments
codex-rs/tui/src/app.rs
- Created: 2025-07-25 21:12:39 UTC | Link: https://github.com/openai/codex/pull/1683#discussion_r2232016460
@@ -88,39 +88,51 @@ impl App<'_> {
{
let app_event_tx = app_event_tx.clone();
std::thread::spawn(move || {
- while let Ok(event) = crossterm::event::read() {
- match event {
- crossterm::event::Event::Key(key_event) => {
- app_event_tx.send(AppEvent::KeyEvent(key_event));
- }
- crossterm::event::Event::Resize(_, _) => {
- app_event_tx.send(AppEvent::RequestRedraw);
- }
- crossterm::event::Event::Mouse(MouseEvent {
- kind: MouseEventKind::ScrollUp,
- ..
- }) => {
- scroll_event_helper.scroll_up();
- }
- crossterm::event::Event::Mouse(MouseEvent {
- kind: MouseEventKind::ScrollDown,
- ..
- }) => {
- scroll_event_helper.scroll_down();
- }
- crossterm::event::Event::Paste(pasted) => {
- // Many terminals convert newlines to \r when
- // pasting, e.g. [iTerm2][]. But [tui-textarea
- // expects \n][tui-textarea]. This seems like a bug
- // in tui-textarea IMO, but work around it for now.
- // [tui-textarea]: https://github.com/rhysd/tui-textarea/blob/4d18622eeac13b309e0ff6a55a46ac6706da68cf/src/textarea.rs#L782-L783
- // [iTerm2]: https://github.com/gnachman/iTerm2/blob/5d0c0d9f68523cbd0494dad5422998964a2ecd8d/sources/iTermPasteHelper.m#L206-L216
- let pasted = pasted.replace("\r", "\n");
- app_event_tx.send(AppEvent::Paste(pasted));
- }
- _ => {
- // Ignore any other events.
+ loop {
+ // This timeout is necessary to avoid holding the event lock
+ // that crossterm::event::read() acquires. In particular,
+ // reading the cursor position (crossterm::cursor::position())
+ // needs to acquire the event lock, and so will fail if it
+ // can't acquire it within 2 sec. Resizing the terminal
+ // crashes the app if the cursor position can't be read.
+ if let Ok(true) = crossterm::event::poll(Duration::from_millis(100)) {
This is...surprising. Maybe link to
9836f0760d/examples/apps/inline/src/main.rs (L98-L118)to cite an example from Ratatui itself?
- Created: 2025-07-25 21:12:49 UTC | Link: https://github.com/openai/codex/pull/1683#discussion_r2232017016
@@ -88,39 +88,51 @@ impl App<'_> {
{
let app_event_tx = app_event_tx.clone();
std::thread::spawn(move || {
- while let Ok(event) = crossterm::event::read() {
- match event {
- crossterm::event::Event::Key(key_event) => {
- app_event_tx.send(AppEvent::KeyEvent(key_event));
- }
- crossterm::event::Event::Resize(_, _) => {
- app_event_tx.send(AppEvent::RequestRedraw);
- }
- crossterm::event::Event::Mouse(MouseEvent {
- kind: MouseEventKind::ScrollUp,
- ..
- }) => {
- scroll_event_helper.scroll_up();
- }
- crossterm::event::Event::Mouse(MouseEvent {
- kind: MouseEventKind::ScrollDown,
- ..
- }) => {
- scroll_event_helper.scroll_down();
- }
- crossterm::event::Event::Paste(pasted) => {
- // Many terminals convert newlines to \r when
- // pasting, e.g. [iTerm2][]. But [tui-textarea
- // expects \n][tui-textarea]. This seems like a bug
- // in tui-textarea IMO, but work around it for now.
- // [tui-textarea]: https://github.com/rhysd/tui-textarea/blob/4d18622eeac13b309e0ff6a55a46ac6706da68cf/src/textarea.rs#L782-L783
- // [iTerm2]: https://github.com/gnachman/iTerm2/blob/5d0c0d9f68523cbd0494dad5422998964a2ecd8d/sources/iTermPasteHelper.m#L206-L216
- let pasted = pasted.replace("\r", "\n");
- app_event_tx.send(AppEvent::Paste(pasted));
- }
- _ => {
- // Ignore any other events.
+ loop {
+ // This timeout is necessary to avoid holding the event lock
+ // that crossterm::event::read() acquires. In particular,
+ // reading the cursor position (crossterm::cursor::position())
+ // needs to acquire the event lock, and so will fail if it
+ // can't acquire it within 2 sec. Resizing the terminal
2 sec or 100ms?
- Created: 2025-07-25 21:14:37 UTC | Link: https://github.com/openai/codex/pull/1683#discussion_r2232019640
@@ -88,39 +88,51 @@ impl App<'_> {
{
let app_event_tx = app_event_tx.clone();
std::thread::spawn(move || {
- while let Ok(event) = crossterm::event::read() {
- match event {
- crossterm::event::Event::Key(key_event) => {
- app_event_tx.send(AppEvent::KeyEvent(key_event));
- }
- crossterm::event::Event::Resize(_, _) => {
- app_event_tx.send(AppEvent::RequestRedraw);
- }
- crossterm::event::Event::Mouse(MouseEvent {
- kind: MouseEventKind::ScrollUp,
- ..
- }) => {
- scroll_event_helper.scroll_up();
- }
- crossterm::event::Event::Mouse(MouseEvent {
- kind: MouseEventKind::ScrollDown,
- ..
- }) => {
- scroll_event_helper.scroll_down();
- }
- crossterm::event::Event::Paste(pasted) => {
- // Many terminals convert newlines to \r when
- // pasting, e.g. [iTerm2][]. But [tui-textarea
- // expects \n][tui-textarea]. This seems like a bug
- // in tui-textarea IMO, but work around it for now.
- // [tui-textarea]: https://github.com/rhysd/tui-textarea/blob/4d18622eeac13b309e0ff6a55a46ac6706da68cf/src/textarea.rs#L782-L783
- // [iTerm2]: https://github.com/gnachman/iTerm2/blob/5d0c0d9f68523cbd0494dad5422998964a2ecd8d/sources/iTermPasteHelper.m#L206-L216
- let pasted = pasted.replace("\r", "\n");
- app_event_tx.send(AppEvent::Paste(pasted));
- }
- _ => {
- // Ignore any other events.
+ loop {
+ // This timeout is necessary to avoid holding the event lock
+ // that crossterm::event::read() acquires. In particular,
+ // reading the cursor position (crossterm::cursor::position())
+ // needs to acquire the event lock, and so will fail if it
+ // can't acquire it within 2 sec. Resizing the terminal
+ // crashes the app if the cursor position can't be read.
+ if let Ok(true) = crossterm::event::poll(Duration::from_millis(100)) {
Also, it looks like that example is doing something slightly different: should we be modeling it more closely?