#interrupt #signal #posix #signals #builder #xvrqt #api-bindings

addy

POSIX中断处理,既安全又易于使用

3个不稳定版本

0.1.1 2020年3月26日
0.1.0 2020年3月26日
0.0.1 2020年3月25日

#376 in Unix APIs


用于 krecik

自定义许可

49KB
421 行代码(不含注释)

Addy

一个用于优雅处理内核中断的库。

快速入门

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(())
}

函数

中介

这为您提供了一个SignalHandle,表示您想要交互的中断处理器。SignalHandles是线程安全的!您可以从任何地方调用/创建/移动它们!

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(())
}

注册

将回调注册到关联的Signal的中断处理器。如果您使用相同的名称调用register,它将替换先前的回调。

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(())
}

启用

开始捕获中断并调用任何关联的回调。通常在调用.register()之后使用。

等同于 .resume()

 use addy::SIGINT;

 fn main() -> Result<(), addy::Error> {
 	addy::mediate(SIGINT)
				.register("print", |_signal| { println!("Interrupted!"); })?
				.enable()?;
		Ok(())
 }

移除

从关联的Signal中删除一个命名的回调。如果不存在该名称的回调,则不执行任何操作。

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(())
}

清除

从关联的Signal中删除所有回调。功能上类似于调用.ignore(),但您不需要在稍后添加新回调时调用.enable()

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(())
}

释放

从关联的Signal中删除所有回调并将中断处理器重置为默认行为。功能上等同于调用.clear().default()。您需要重新注册回调后再次调用.enable()

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(())
}

忽略

告诉进程忽略此中断。保留所有回调。调用.resume()将重新启用它们。

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(())
}

默认

将中断处理器恢复到系统默认设置。并非所有中断都有默认设置,有些中断的默认设置是忽略。保留所有回调。调用.resume()将重新启用它们。

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(())
}

恢复

捕获中断并调用任何相关回调的简历。通常在调用 .ignore() 和 .default() 之后使用。

是 .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(())
}

注意事项

我爱你,并祝你一切顺利。无论你选择做什么,希望你觉得值得花时间去做好它。

Addy 是线程安全的!

你可以在任何地方、任何时候调用它!你可以将 SignalHandle(来自 addy::mediate(signal))存储在变量中并传递它。

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(())
}

支持的信号

并非所有平台/架构都支持所有信号。你的平台支持哪些信号?运行:kill -l 来查找!

  • 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

错误

如果 MPSC 通道关闭或事件循环线程关闭,将无法恢复,任何未来的 Addy 调用都将返回 addy::Error。

依赖关系

~69KB