Skip to content

Commit ae1b006

Browse files
committed
fix: ignore SIGINT during paging
1 parent 006d77f commit ae1b006

File tree

4 files changed

+45
-7
lines changed

4 files changed

+45
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
## Bugfixes
66

77
- Fix negative values of N not being parsed in <N:M> line ranges without `=` flag value separator, see #3442 (@lmmx)
8+
- Fix bug where less exitted without `-K` arg by ignoring SIGINT during paging, see issue #3444 and PR #3447 (@lmmx)
89

910
## Other
1011

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ execute = { version = "0.2.13", optional = true }
7575
terminal-colorsaurus = "1.0"
7676
unicode-segmentation = "1.12.0"
7777
itertools = "0.14.0"
78+
signal-hook = "0.3.18"
7879

7980
[dependencies.git2]
8081
version = "0.20"

src/output.rs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,36 @@ use crate::paging::PagingMode;
1313
#[cfg(feature = "paging")]
1414
use crate::wrapping::WrappingMode;
1515

16+
#[cfg(all(unix, feature = "paging"))]
17+
use std::sync::atomic::AtomicBool;
18+
#[cfg(all(unix, feature = "paging"))]
19+
use std::sync::Arc;
20+
#[cfg(all(unix, feature = "paging"))]
21+
struct IgnoreSigint {
22+
_handle: signal_hook::SigId,
23+
}
24+
25+
#[cfg(all(unix, feature = "paging"))]
26+
impl IgnoreSigint {
27+
fn new() -> Self {
28+
// No-op SIGINT handler prevents pager process termination
29+
let handle = signal_hook::flag::register(
30+
signal_hook::consts::SIGINT,
31+
Arc::new(AtomicBool::new(false)),
32+
)
33+
.expect("failed to ignore SIGINT");
34+
35+
Self { _handle: handle }
36+
}
37+
}
38+
39+
#[cfg(feature = "paging")]
40+
pub struct PagerProc {
41+
child: Child,
42+
#[cfg(unix)]
43+
_sigint_guard: IgnoreSigint,
44+
}
45+
1646
#[cfg(feature = "paging")]
1747
pub struct BuiltinPager {
1848
pager: minus::Pager,
@@ -50,10 +80,9 @@ enum SingleScreenAction {
5080
Nothing,
5181
}
5282

53-
#[derive(Debug)]
5483
pub enum OutputType {
5584
#[cfg(feature = "paging")]
56-
Pager(Child),
85+
Pager(PagerProc),
5786
#[cfg(feature = "paging")]
5887
BuiltinPager(BuiltinPager),
5988
Stdout(io::Stdout),
@@ -166,7 +195,13 @@ impl OutputType {
166195

167196
Ok(p.stdin(Stdio::piped())
168197
.spawn()
169-
.map(OutputType::Pager)
198+
.map(|child| {
199+
OutputType::Pager(PagerProc {
200+
child,
201+
#[cfg(unix)]
202+
_sigint_guard: IgnoreSigint::new(),
203+
})
204+
})
170205
.unwrap_or_else(|_| OutputType::stdout()))
171206
}
172207

@@ -187,8 +222,8 @@ impl OutputType {
187222
pub fn handle<'a>(&'a mut self) -> Result<OutputHandle<'a>> {
188223
Ok(match *self {
189224
#[cfg(feature = "paging")]
190-
OutputType::Pager(ref mut command) => OutputHandle::IoWrite(
191-
command
225+
OutputType::Pager(ref mut proc) => OutputHandle::IoWrite(
226+
proc.child
192227
.stdin
193228
.as_mut()
194229
.ok_or("Could not open stdin for pager")?,
@@ -204,8 +239,8 @@ impl OutputType {
204239
impl Drop for OutputType {
205240
fn drop(&mut self) {
206241
match *self {
207-
OutputType::Pager(ref mut command) => {
208-
let _ = command.wait();
242+
OutputType::Pager(ref mut proc) => {
243+
let _ = proc.child.wait();
209244
}
210245
OutputType::BuiltinPager(ref mut pager) => {
211246
if pager.handle.is_some() {

0 commit comments

Comments
 (0)