Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Output, Errors, and Early Exit

Parallel work is only half of the design. Ripgrep must also decide what becomes observable when work completes out of order, fails, or is no longer needed.

Atomic output units

Each worker prints into a private termcolor::Buffer. After one file finishes, BufferWriter::print writes the completed buffer to stdout. The synchronization boundary is therefore one file’s rendered result, not one match and not the whole search.

This is a useful general pattern:

compute concurrently → stage result privately → commit as one visible unit

It preserves throughput without holding a global stdout lock throughout file I/O and matching.

Determinism costs parallelism

Parallel workers finish in scheduler- and filesystem-dependent order. Ripgrep therefore cannot promise stable file ordering in its normal parallel mode. When sorting is requested, HiArgs forces the effective thread count to one; the sequential path can then sort before searching.

Source: HiArgs thread selection, walk_builder

The important tradeoff is not “sorting is slow.” Global order requires knowing which result comes next, so the existing immediate-commit architecture cannot retain both its bounded buffering and arbitrary parallel completion.

Most file errors are partial failures

An unreadable directory or failed file search is reported, but other workers continue. A shared error indicator later influences the process exit code. This lets a search produce useful matches even when one subtree is inaccessible.

Fatal initialization errors still return through anyhow::Result; per-entry operational errors are logged and converted into WalkState::Continue.

Broken pipe is successful termination

If a downstream consumer closes the pipe—rg pattern | head, for example—an output write returns BrokenPipe. The parallel visitor returns WalkState::Quit, and top-level error handling treats a propagated broken pipe as exit code zero.

Source: search_parallel output handling, main error mapping

Quiet mode coordinates early exit

When one worker finds a match, it stores true in the shared matched atomic. If the selected mode permits stopping after a match, that worker returns WalkState::Quit. Worker::run sets the global quit flag, so peers stop taking ordinary work at their next coordination point.

This is cooperative cancellation. A worker already inside a synchronous file read is not forcibly interrupted; shutdown happens at explicit boundaries.

Panic cleanup

Traversal uses scoped threads and joins every handle. If a Worker is dropped while its thread is panicking, its Drop implementation sets the same global quit flag, encouraging peers to stop rather than continue unrelated work.

Source: Worker::drop