3 unstable releases
0.1.1 | Mar 26, 2020 |
---|---|
0.1.0 | Mar 26, 2020 |
0.0.1 | Mar 25, 2020 |
#483 in Unix APIs
Used in krecik
49KB
421 lines
Addy
A library for ergonomically handling kernel interrupts.
Quick Start
use addy::SIGWINCH;
use std::io::{Read, stdin};
fn main() -> Result<(), addy::Error> {
/* SIGWINCH is a POSIX interrupt signal for window resized */
addy::mediate(SIGWINCH)
.register("print", |_signal| { println!("Screen Resized!"); })?
.enable()?;
/* Block so the program doesn't exit immediately
* Try resizing your terminal window :)
*/
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()?;
/* Block so the program doesn't exit immediately
* Try resizing your terminal window :)
*/
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) {
/* Does a thing */
}
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) {
/* Does a thing */
}
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("print", |_signal| { println!("Screen Resized!"); })?
.register("my_func", my_func)?
.enable()?;
//-- Later --//
// Stop calling "print" when the process receives a SIGWINCH signal
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) {
/* Does a thing */
}
fn main() -> Result<(), addy::Error> {
addy::mediate(SIGWINCH)
.register("print", |_signal| { println!("Screen Resized!"); })?
.register("my_func", my_func)?
.enable()?;
//-- Later --//
// Capture the signal, but stop calling anything
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()?;
//-- Later --//
// Stop capturing the signal
addy::mediate(SIGWINCH).release()?;
//-- Later Still --//
// Start catpuring again
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()?;
//-- Later --//
// Ignore the signal
addy::mediate(SIGWINCH).ignore()?;
//-- Later Still --//
// Start catpuring again
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()?;
//-- Later --//
// Set the signal to its default
addy::mediate(SIGINT).default()?;
//-- Later Still --//
// Start catpuring again
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()?;
//-- Later --//
// Set the signal to its default
addy::mediate(SIGINT).default()?;
//-- Later Still --//
// Start catpuring and printing "Interrupted!" again
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> {
/* When the window resizes */
addy::mediate(SIGWINCH)
.register("hello", |_signal| { println!("Hello, World!"); })?
.register("girls", |_signal| { println!("Hello, Girls!"); })?
.enable()?;
/* SIGINT is sent when the user presses Ctrl + C. The default behavior is
* to interrupt the program's execution.
*/
let mut ctrl_c = addy::mediate(SIGINT);
ctrl_c.register("no_interruptions", |_signal| { println!("{}", QUOTE); })?.enable()?;
/* Let the user use Ctrl + C to kill the program after 10 seconds */
std::thread::spawn(move || -> Result<(), addy::Error> {
std::thread::sleep(std::time::Duration::from_secs(10));
ctrl_c.default()?;
Ok(())
});
/* Stop saying "Hello, World!" on resize after 5 seconds */
std::thread::spawn(move || -> Result<(), addy::Error> {
std::thread::sleep(std::time::Duration::from_secs(5));
addy::mediate(SIGWINCH).remove("hello")?;
Ok(())
});
/* Capture the input so we don't exit the program immediately */
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.
Dependencies
~70KB