signals-but-a-little-nicer

Crates.iosignals-but-a-little-nicer
lib.rssignals-but-a-little-nicer
version1.0.0
created_at2025-07-08 00:42:37.933717+00
updated_at2025-07-08 00:42:37.933717+00
descriptionA wrapper around signal-handlers for Windows [console applications] and Unix programs.
homepagehttps://github.com/rtldg/signals-but-a-little-nicer
repositoryhttps://github.com/rtldg/signals-but-a-little-nicer
max_upload_size
id1741923
size26,904
rtldg (rtldg)

documentation

README

signals-but-a-little-nicer

Crates Docs

A wrapper around signal-handlers for Windows [console applications] and Unix programs.

Signals in Unix are a bad API. A clean way to handle them is to block signals on all threads and create a dedicated thread to wait on them. Which is what this does...

Only a few signals are caught: SIGINT, SIGTERM, SIGHUP, SIGQUIT, SIGUSR1, and SIGUSR2.

Why?

You can do everything and more with signal-hook or async-signal but I explicitly want to block signals on all threads on Unix/Linux (and then use sigwait(3)).

Example

fn main() {
	let signal_recv = signals_but_a_little_nicer::get_or_init_recv().unwrap();
	println!("hit CTRL+C...");
	std::thread::sleep(std::time::Duration::from_secs(3));

	if signal_recv.len() == 0 {
		println!("you didn't hit CTRL+C :(");
	} else {
		while let Ok(signal) = signal_recv.try_recv() {
			println!(" received {signal:?}!");
		}
	}
}

Also note that you'll want to register the handler before creating threads (or say a tokio runtime):

use anyhow::Context;

fn main() -> anyhow::Result<()> {
	let signal_recv = signals_but_a_little_nicer::get_or_init_receiver().context("failed to setup signal handler")?;
	let rt = tokio::runtime::Runtime::new()?;
	rt.block_on(async { tokio::spawn(async_main(signal_recv)).await? })
}

async fn async_main(mut signal_recv: signals_but_a_little_nicer::SignalReceiver) -> anyhow::Result<()> {
	tokio::spawn(async {
		tokio::time::sleep(std::time::Duration::from_secs(3)).await;
		std::process::exit(0);
	});
	while let Ok(signal) = signal_recv.recv().await {
		println!("signal received: {signal:?}");
	}
	Ok(())
}

Commit count: 0

cargo fmt