Skip to content

Conversation

@lmmx
Copy link
Contributor

@lmmx lmmx commented Oct 20, 2025

Bug

When BAT_PAGER='less -R' is set (without -K), pressing Ctrl-C still exits less immediately instead of canceling the current operation and staying open. This happens because bat receives SIGINT and begins teardown, which causes less to lose access to the TTY and exit with EIO.

Solution

Use signal-hook to temporarily ignore SIGINT in bat while the pager is active. This allows less to handle Ctrl-C independently. When the pager exits, the signal handler is automatically restored via RAII.

Specifically I registered a dummy flag that's never checked. This prevents the default SIGINT handler from terminating the process, effectively ignoring the signal.

Changes

  • Added IgnoreSigint RAII guard that ignores SIGINT while alive
  • Wrapped Child in PagerProc struct to carry the signal guard
  • Signal guard is created when spawning external pagers and dropped when pager exits

Now Ctrl-C behaves correctly in less:

  • Without -K: cancels search/operation, stays open
  • With -K: exits immediately (existing behavior preserved)

Demo

Before: Ctrl C closes the pager but neither does the terminal fully regain control. You have to press Ctrl + C again

for i in {0..100}; do echo $i; done | BAT_PAGER='less -R' bat

After: Ctrl + C sends SIGINT and bat actively ignores it, hence does not kill the pager process via teardown

for i in {0..100}; do echo $i; done | BAT_PAGER='less -R' ./target/debug/bat

Status

  • Changelog entry applied
  • No docs, this is a fulfillment of already documented behaviour in the pager section of the README
  • Ready for review: yes

@lmmx lmmx force-pushed the ignore-sigint-paging branch 2 times, most recently from d4ab52e to ae1b006 Compare October 20, 2025 10:34
@lmmx lmmx changed the title [DRAFT] fix: Ctrl-C forces less to exit when BAT_PAGER doesn't include -K fix: prevent Ctrl+C from killing bat when paging without -K Oct 20, 2025
@lmmx lmmx marked this pull request as ready for review October 20, 2025 10:41
@lmmx lmmx marked this pull request as draft October 20, 2025 10:45
@lmmx lmmx marked this pull request as ready for review October 20, 2025 13:17
pub enum OutputType {
#[cfg(feature = "paging")]
Pager(Child),
Pager(PagerProc),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Note: this changes the public API (for bat as a library), so to be semver compatible, the next release including this cannot be a patch release

Copy link
Contributor Author

@lmmx lmmx Oct 20, 2025

Choose a reason for hiding this comment

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

hmm, ok. Let me know if I can alleviate any of the friction to do with that. Also: if it’s not something you’re wholly behind don’t feel obliged to merge it.

I feel like it solves the bug in terms of UX but not correct way (i.e. bat stays alive). Whether there are implications to bat staying alive I’m not quite sure though. Unlike most programs bat isn’t going to be producing a stream of data (if I follow it correctly?)

I am not fully certain how to think about the case of bat reading a large file into a pager, I wouldn’t imagine that to be a runaway process you might want to Ctrl+C to stop and then stay in the pager to read the partial result of. But I might be wrong.

If that view is right though, bat living on and just ignoring SIGINT seems “basically fine”

@lmmx lmmx marked this pull request as draft October 20, 2025 18:37
@lmmx lmmx force-pushed the ignore-sigint-paging branch from cff3a0c to e4c6369 Compare October 20, 2025 18:40
@lmmx lmmx force-pushed the ignore-sigint-paging branch from e4c6369 to 586ff04 Compare October 20, 2025 18:40
@lmmx lmmx marked this pull request as ready for review October 20, 2025 18:41
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.

ctrl-c still exits less, even when bat isn't passing --quit-on-intr

2 participants