Tech News
← Back to articles

Fixing Ctrl+C in Rust terminal apps: Child process management

read original related products more articles

When a terminal application that spawns child processes doesn't exit cleanly after a Ctrl+C , the user is left with a corrupted terminal. Instead of a clean prompt, you get garbled output and a non-functional shell. This post covers how to solve these issues, with examples from the Moose CLI (for the PR that fixed many of these issues, see here).

In this post, you’ll read learnings from solving these issues in the Moose CLI— terminal application that manages multiple child processes, including Docker containers, TypeScript compilers, and background workers.

The Problems: Terminal Corruption and Hanging Processes

Terminal corruption manifests in several ways:

Terminal State Corruption: After Ctrl+C, the terminal cursor might be hidden, raw mode might still be enabled, or the alternate screen buffer might still be active Child Process Output Interference: Child processes continue writing to stdout/stderr, mixing with your shell prompt Hanging Background Processes: Child processes don't receive proper termination signals and continue running Race Conditions: Cleanup code races with child process output, leading to unpredictable terminal state

How We Solved It

1. Process Output Proxying

Child process output must be completely isolated from the terminal. Direct child process output to the terminal creates race conditions and corruption.

Key principles:

Pipe all child process stdio : Use Stdio::piped() for stdout/stderr and Stdio::null() for stdin. Stdio::piped() will create a new pipe that is going to be readable by the parent process but will only be written to the stdout of the parent if explicitly done. And Stdio::null() will enable to ignore the inputs.

... continue reading