Addy
A library for ergonomically handling kernel interrupts.
Quick Start
use addy::SIGWINCH;
use std::io::{Read, stdin};
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("print", |_signal| { println!("Screen Resized!"); })?
.enable()?;
let mut buffer = [0; 1];
loop {
stdin().read(&mut buffer);
}
Ok(())
}
Functions
Mediate
This gives you a SignalHandle representing the interrupt handler you want to interact with. SignalHandles are threadsafe! Call/create/move them anywhere from anywhere!
use addy::SIGWINCH;
use std::io::{Read, stdin};
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("resized", |_signal| { println!("Screen Resized!"); })?
.enable()?;
let mut buffer = [0; 1];
loop {
stdin().read(&mut buffer);
}
Ok(())
}
Register
Registers a callback with the interrupt handler for the associated Signal. If you call register with the same name it will replace the previous callback.
use addy::{Signal, SIGWINCH};
fn my_func(signal: Signal) {
}
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("print", |_signal| { println!("Screen Resized!"); })?
.register("my_func", my_func)?
.enable()?;
Ok(())
}
Enable
Begins capturing the interrupt and calling any associated callbacks. Most often used after a calls .register()
Alias of .resume()
use addy::SIGINT;
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGINT)
.register("print", |_signal| { println!("Interrupted!"); })?
.enable()?;
Ok(())
}
Remove
Removes a named callback from the associated Signal. If no callback with that name exists, it does nothing.
use addy::{Signal, SIGWINCH};
fn my_func(signal: Signal) {
}
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("print", |_signal| { println!("Screen Resized!"); })?
.register("my_func", my_func)?
.enable()?;
addy::mediate(SIGWINCH).remove("print")?;
Ok(())
}
Clear
Removes a all callbacks from the associated Signal. Functionally similar
to calling .ignore()
except you don't need to call .enable()
if you add
new callbacks later.
use addy::{Signal, SIGWINCH};
fn my_func(signal: Signal) {
}
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("print", |_signal| { println!("Screen Resized!"); })?
.register("my_func", my_func)?
.enable()?;
addy::mediate(SIGWINCH)
.clear()?
.register("solo_callback", |_signal| { println!("ALONE!"); })?;
Ok(())
}
Release
Removes a all callbacks from the associated Signal and resets the interrupt handler to the default behavior. Funcationally the same as calling .clear()
and .default()
You will need to call .enable()
again after re-registering callbacks.
use addy::SIGWINCH;
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("print", |_signal| { println!("Screen Resized!"); })?
.enable()?;
addy::mediate(SIGWINCH).release()?;
addy::mediate(SIGWINCH)
.register("new", |_signal| { println!("New callback!"); })?
.enable()?;
Ok(())
}
Ignore
Tells the process to ignore this interrupt. Keeps all your callbacks. Calling .resume()
will re-enable them.
use addy::SIGWINCH;
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("print", |_signal| { println!("Screen Resized!"); })?
.enable()?;
addy::mediate(SIGWINCH).ignore()?;
addy::mediate(SIGWINCH).resume()?;
Ok(())
}
Default
Restore the interrupt handler to the system default. Not all interrupts have a default, and some interrupts default is to be ignored. Keeps all your callbacks. Calling .resume()
will re-enable them.
use addy::SIGINT;
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGINT)
.register("print", |_signal| { println!("Interrupted!"); })?
.enable()?;
addy::mediate(SIGINT).default()?;
addy::mediate(SIGINT).resume()?;
Ok(())
}
Resume
Resumes capturing the interrupt and calling any associated callbacks. Most often used after a call to .ignore() and .default().
Alias of .enable()
use addy::SIGINT;
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGINT)
.register("print", |_signal| { println!("Interrupted!"); })?
.enable()?;
addy::mediate(SIGINT).default()?;
addy::mediate(SIGINT).resume()?;
Ok(())
}
Things To Know
I love you and I wish the best for you. No matter what you choose to do, I hope you decide it is worth you time to do it well.
Addy is Thread Safe!
You can call it from anywhere, at anytime! You can store a SignalHandle (returned from addy::mediate(signal)) in a variable and pass it around.
use addy::{SIGWINCH, SIGINT};
use std::io::{Read, stdin};
static QUOTE: &'static str = "Look at you, hacker: a pathetic creature of meat \
and bone, panting and sweating as you run through \
my corridors. How can you challenge a perfect, \
immortal machine?";
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("hello", |_signal| { println!("Hello, World!"); })?
.register("girls", |_signal| { println!("Hello, Girls!"); })?
.enable()?;
let mut ctrl_c = addy::mediate(SIGINT);
ctrl_c.register("no_interruptions", |_signal| { println!("{}", QUOTE); })?.enable()?;
std::thread::spawn(move || -> Result<(), addy::Error> {
std::thread::sleep(std::time::Duration::from_secs(10));
ctrl_c.default()?;
Ok(())
});
std::thread::spawn(move || -> Result<(), addy::Error> {
std::thread::sleep(std::time::Duration::from_secs(5));
addy::mediate(SIGWINCH).remove("hello")?;
Ok(())
});
let mut buffer = [0; 1];
loop {
stdin().read(&mut buffer);
}
Ok(())
}
Signals Supported
Not all signals are supported on all platforms/architectures. Which signals
does your platform support? Run: kill -l
to find out!
- SIGHUP
- SIGINT
- SIGQUIT
- SIGILL
- SIGTRAP
- SIGABRT
- SIGBUS
- SIGFPE
- SIGKILL
- SIGUSR1
- SIGSEGV
- SIGUSR2
- SIGPIPE
- SIGALRM
- SIGTERM
- SIGSTKF
- SIGCHLD
- SIGCONT
- SIGSTOP
- SIGTSTP
- SIGTTIN
- SIGTTOU
- SIGURG
- SIGXCPU
- SIGXFSZ
- SIGVTAL
- SIGPROF
- SIGWINC
- SIGIO
- SIGPWR
- SIGSYS
- SIGEMT
- SIGINFO
Errors
If the MPSC channel closes, of the Event Loop thread closes, there is no way to recover and any future Addy calls will return an addy::Error.