Skip to content

Commit

Permalink
new: interrupt-ignore-count command-line option with default value of 3
Browse files Browse the repository at this point in the history
  • Loading branch information
pamburus committed Aug 19, 2020
1 parent a3f9638 commit a26343f
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 3 deletions.
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ structopt = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["raw_value"] }
shellwords = "1.1"
signal-hook = "0.1"

[dependencies.itoa]
version = "0.4.3"
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod input;
mod model;
pub mod output;
mod scanning;
pub mod signal;
pub mod theme;
pub mod timestamp;
pub mod types;
Expand Down
20 changes: 17 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
// std imports
use std::env;
use std::path::PathBuf;
use std::process;
use std::sync::Arc;
use std::time::Duration;

// third-party imports
use ansi_term::Colour;
use isatty::stdout_isatty;
use structopt::clap::arg_enum;
use structopt::StructOpt;

// local imports
use hl::datefmt::LinuxDateFormat;
use hl::error::*;
use hl::input::{open, ConcatReader, Input, InputStream};
use hl::output::{OutputStream, Pager};
use hl::signal::SignalHandler;

// ---

/// JSON log converter to human readable representation.
#[derive(StructOpt)]
Expand All @@ -37,6 +44,10 @@ struct Opt {
#[structopt(short, long)]
raw_fields: bool,
//
/// Number of interrupts to ignore, i.e. Ctrl-C (SIGINT).
#[structopt(short, long, default_value = "3")]
interrupt_ignore_count: usize,
//
/// Buffer size, kibibytes.
#[structopt(long, default_value = "2048")]
buffer_size: usize,
Expand Down Expand Up @@ -197,12 +208,15 @@ fn run() -> Result<()> {
Box::new(std::io::stdout())
};

// Run app.
match app.run(input.as_mut(), output.as_mut()) {
// Run the app.
let run = || match app.run(input.as_mut(), output.as_mut()) {
Ok(()) => Ok(()),
Err(Error(ErrorKind::Io(ref e), _)) if e.kind() == std::io::ErrorKind::BrokenPipe => Ok(()),
Err(err) => Err(err),
}
};

// Run the app with signal handling.
SignalHandler::run(opt.interrupt_ignore_count, Duration::from_secs(1), run)
}

fn main() {
Expand Down
69 changes: 69 additions & 0 deletions src/signal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// std imports
use std::process::exit;
use std::thread::{spawn, JoinHandle};
use std::time::{Duration, Instant};

// third-party imports
use signal_hook::{iterator::Signals, SIGINT};

// local imports
use crate::error::*;

// ---

pub struct SignalHandler {
signals: Signals,
thread: Option<JoinHandle<()>>,
}

impl SignalHandler {
pub fn run<F>(max_count: usize, timeout: Duration, f: F) -> Result<()>
where
F: FnOnce() -> Result<()>,
{
let _guard = Self::new(max_count, timeout)?;
f()
}

fn new(max_count: usize, timeout: Duration) -> Result<Self> {
let signals = Signals::new(&[SIGINT])?;
let s = signals.clone();

let thread = spawn(move || {
let mut count = 0;
let mut ts = Instant::now();
for signal in &s {
match signal {
SIGINT => {
if count < max_count {
count += 1;
}
let now = Instant::now();
if now.duration_since(ts) > timeout {
count = 0;
}
if count == max_count {
exit(0x80 + signal);
}
ts = now;
}
_ => unreachable!(),
}
}
});

Ok(Self {
signals,
thread: Some(thread),
})
}
}

impl Drop for SignalHandler {
fn drop(&mut self) {
self.signals.close();
if let Some(thread) = self.thread.take() {
thread.join().unwrap();
}
}
}

0 comments on commit a26343f

Please sign in to comment.