[PR #100] [MERGED] fix(tui): move signal handler registration after TUI initialization #131

Closed
opened 2026-02-27 10:22:21 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/mikeyobrien/ralph-orchestrator/pull/100
Author: @memyselfandm
Created: 1/23/2026
Status: Merged
Merged: 1/23/2026
Merged by: @mikeyobrien

Base: mainHead: fix/tui-signal-handler-deadlock


📝 Commits (1)

  • a768f1d fix(tui): move signal handler registration after TUI initialization

📊 Changes

1 file changed (+41 additions, -37 deletions)

View changed files

📝 crates/ralph-cli/src/loop_runner.rs (+41 -37)

📄 Description

Summary

Fixes #99 - Resolves TUI hang on startup caused by deadlock between tokio signal handlers and crossterm initialization on macOS.

Problem

Ralph v2.2.1 hung silently on startup when TUI was enabled (default behavior), but worked correctly with --no-tui flag. This was a regression introduced by the refactor in commit f0af5d6 (PR #97).

Root Cause

Deadlock between tokio signal handlers and crossterm TUI initialization:

  1. Signal handlers (ctrl_c, SIGTERM, SIGHUP) were spawned at lines 84-117
  2. TUI was spawned at line 243 which calls enable_raw_mode() and creates EventStream
  3. On macOS, crossterm's EventStream creation conflicted with already-registered tokio signal handlers

Solution

Move signal handler registration to after TUI initialization completes (after the 100ms sleep at line 253).

Before:

1. Register signal handlers
2. Initialize event loop  
3. Spawn TUI task
4. Sleep 100ms for TUI init
5. Start orchestration loop

After:

1. Create signal channel
2. Initialize event loop
3. Spawn TUI task
4. Sleep 100ms for TUI init
5. Register signal handlers ← MOVED HERE
6. Start orchestration loop

This ensures TUI enters raw mode and creates EventStream before signal handlers are registered, preventing the deadlock.

Testing

  • All tests passing (345 unit tests)
  • Smoke tests passing (12 replay-based tests)
  • Manual validation: TUI now appears immediately on macOS
  • Verified --no-tui mode still works
  • Confirmed Ctrl+C handling works correctly

Validation Steps

Tested on macOS (Darwin 25.1.0) with iTerm2:

# Previously: hung silently
# Now: works correctly
ralph run -p "test prompt"

TUI renders immediately with header, iteration info, and proceeds with orchestration.

Impact

  • Fixes: TUI mode on macOS
  • No impact: --no-tui mode (was already working)
  • No breaking changes: Signal handling behavior unchanged, just initialization order

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/mikeyobrien/ralph-orchestrator/pull/100 **Author:** [@memyselfandm](https://github.com/memyselfandm) **Created:** 1/23/2026 **Status:** ✅ Merged **Merged:** 1/23/2026 **Merged by:** [@mikeyobrien](https://github.com/mikeyobrien) **Base:** `main` ← **Head:** `fix/tui-signal-handler-deadlock` --- ### 📝 Commits (1) - [`a768f1d`](https://github.com/mikeyobrien/ralph-orchestrator/commit/a768f1d569e32bf1000ba78c6a66ad3083db9141) fix(tui): move signal handler registration after TUI initialization ### 📊 Changes **1 file changed** (+41 additions, -37 deletions) <details> <summary>View changed files</summary> 📝 `crates/ralph-cli/src/loop_runner.rs` (+41 -37) </details> ### 📄 Description ## Summary Fixes #99 - Resolves TUI hang on startup caused by deadlock between tokio signal handlers and crossterm initialization on macOS. ## Problem Ralph v2.2.1 hung silently on startup when TUI was enabled (default behavior), but worked correctly with `--no-tui` flag. This was a regression introduced by the refactor in commit `f0af5d6` (PR #97). ### Root Cause Deadlock between tokio signal handlers and crossterm TUI initialization: 1. Signal handlers (ctrl_c, SIGTERM, SIGHUP) were spawned at lines 84-117 2. TUI was spawned at line 243 which calls `enable_raw_mode()` and creates `EventStream` 3. On macOS, crossterm's EventStream creation conflicted with already-registered tokio signal handlers ## Solution Move signal handler registration to **after** TUI initialization completes (after the 100ms sleep at line 253). **Before:** ``` 1. Register signal handlers 2. Initialize event loop 3. Spawn TUI task 4. Sleep 100ms for TUI init 5. Start orchestration loop ``` **After:** ``` 1. Create signal channel 2. Initialize event loop 3. Spawn TUI task 4. Sleep 100ms for TUI init 5. Register signal handlers ← MOVED HERE 6. Start orchestration loop ``` This ensures TUI enters raw mode and creates EventStream before signal handlers are registered, preventing the deadlock. ## Testing - ✅ All tests passing (345 unit tests) - ✅ Smoke tests passing (12 replay-based tests) - ✅ Manual validation: TUI now appears immediately on macOS - ✅ Verified --no-tui mode still works - ✅ Confirmed Ctrl+C handling works correctly ## Validation Steps Tested on macOS (Darwin 25.1.0) with iTerm2: ```bash # Previously: hung silently # Now: works correctly ralph run -p "test prompt" ``` TUI renders immediately with header, iteration info, and proceeds with orchestration. ## Impact - **Fixes**: TUI mode on macOS - **No impact**: --no-tui mode (was already working) - **No breaking changes**: Signal handling behavior unchanged, just initialization order --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-02-27 10:22:21 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ralph-orchestrator#131
No description provided.