Skip to content

fix: avoid double-borrow panic on rapid Ctrl+Tab tab switching - #113

Open
ferdinankurnian wants to merge 1 commit into
am-will:mainfrom
ferdinankurnian:fix/ctrl-tab-crash
Open

fix: avoid double-borrow panic on rapid Ctrl+Tab tab switching#113
ferdinankurnian wants to merge 1 commit into
am-will:mainfrom
ferdinankurnian:fix/ctrl-tab-crash

Conversation

@ferdinankurnian

Copy link
Copy Markdown

Summary

Fixes a crash caused by a double-borrow panic on TabState's RefCell when rapidly switching tabs with Ctrl+Tab.

Root cause

activate_tab() in pane.rs held tab_state.borrow_mut() across the call to content_stack.set_visible_child_name(tab_id). That GTK call synchronously fires an unmap/map signal cascade on the old and new tab content — including hover/crossing signals on the terminal surface, whose callback calls tab_rename_active(&tab_state), which needs tab_state.borrow().

A single tab switch usually completes (and drops the borrow) before the next signal fires, so it goes unnoticed. But pressing Ctrl+Tab rapidly (2-4x in quick succession) can start a second activate_tab() call while the first switch's unmap cascade is still resolving, causing the reentrant .borrow() to panic while the outer .borrow_mut() is still held — and since this happens inside a GTK/glib signal callback (FFI boundary), the panic can't unwind and the process aborts (SIGABRT).

Fix

Narrowed the borrow_mut() scope so it's dropped before content_stack.set_visible_child_name() is called, removing the reentrancy window.

Testing

  • Reproduced the crash consistently on the release build from AUR (limux-bin) before applying the fix — rapid Ctrl+Tab (2-4 presses) crashed every time
  • Applied the fix, built v0.1.22 via this repo's Build Linux Release Packages workflow, downloaded and ran the resulting build locally — rapid Ctrl+Tab no longer crashes
  • Rust Quality workflow (build, clippy, fmt) passes on the fix commit

Fixes #111

@ferdinankurnian

Copy link
Copy Markdown
Author

Here's the recording confirming the fix, rapid Ctrl+Tab, no crash:

recording_2026-07-11_17-14-12.mp4

@bvolpato bvolpato left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Scoped RefCell borrow removes GTK reentrancy panic while preserving focus behavior.

.find(|entry| entry.id == tab_id)
.map(TabFocusTarget::from_entry);

(focus_target, content_stack.child_by_name(tab_id).is_some())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: move child_by_name() below this scope. Current comment says content_stack is untouched until ts drops, but this query still runs under borrow_mut(). It is likely signal-free; keeping all stack calls outside makes reentrancy boundary explicit.

@bvolpato bvolpato left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. activate_tab now drops mutable TabState borrow before set_visible_child_name() triggers synchronous GTK callbacks. Active-tab styling and deferred terminal/browser focus stay intact. No overlap with control-socket or Ghostty changes in #112 or #114.

(Review assisted by gpt-5.6-sol)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Repeatedly pressing Ctrl+Tab crashes limux

2 participants