Rust异步信号处理库compio-signal的使用,compio-signal提供高性能异步信号捕获与处理功能

compio-logo

compio-signal 简介

compio-signal是一个基于compio运行时的高性能异步信号处理库,提供信号捕获与处理功能。它是compio生态系统的一部分,采用完成式IO模型(IOCP/io_uring/polling)。

安装

在Cargo.toml中添加依赖:

compio-signal = "0.6.0"

或者运行:

cargo add compio-signal

使用示例

以下是使用compio-signal捕获和处理SIGINT信号的完整示例:

use compio::signal::{ctrl_c, Signal};

#[compio::main]
async fn main() {
    // 方式1:使用ctrl_c捕获Ctrl+C信号
    let ctrl_c = ctrl_c().await.unwrap();
    println!("Ctrl+C received!");
    
    // 方式2:创建信号流处理多个信号
    let mut signal = Signal::new(libc::SIGINT).unwrap();
    loop {
        signal.recv().await.unwrap();
        println!("SIGINT received!");
    }
}

高级用法

use compio::signal::{Signal, SignalSet};
use libc::{SIGINT, SIGTERM};

#[compio::main]
async fn main() {
    // 创建信号集处理多个信号
    let mut set = SignalSet::new(&[SIGINT, SIGTERM]).unwrap();
    
    loop {
        let sig = set.recv().await.unwrap();
        match sig {
            SIGINT => println!("SIGINT received!"),
            SIGTERM => {
                println!("SIGTERM received, exiting...");
                break;
            },
            _ => unreachable!(),
        }
    }
}

完整示例代码

下面是一个更完整的示例,展示了如何优雅地处理多个信号并实现优雅退出:

use compio::signal::{Signal, SignalSet};
use libc::{SIGINT, SIGTERM, SIGHUP};

#[compio::main]
async fn main() {
    // 创建信号集处理多种信号
    let mut set = SignalSet::new(&[SIGINT, SIGTERM, SIGHUP]).unwrap();
    
    println!("Server started, PID = {}", std::process::id());
    println!("Press Ctrl+C or send SIGTERM/SIGHUP to exit");
    
    loop {
        let sig = set.recv().await.unwrap();
        match sig {
            SIGINT => {
                println!("\nSIGINT received, preparing to exit...");
                // 这里可以添加清理逻辑
                break;
            },
            SIGTERM => {
                println!("\nSIGTERM received, exiting gracefully...");
                // 这里可以添加清理逻辑
                break;
            },
            SIGHUP => {
                println!("\nSIGHUP received, reloading configuration...");
                // 这里可以添加配置重载逻辑
                continue;
            },
            _ => unreachable!(),
        }
    }
    
    println!("Server shutdown complete");
}

特性

  1. 高性能异步信号处理
  2. 支持多种信号类型
  3. 与compio运行时无缝集成
  4. 提供信号流(Stream)接口

注意事项

  • 需要启用compio运行时
  • 仅支持POSIX信号(在Linux/macOS上)
  • 需要处理信号时确保程序不会意外退出

compio-signal是compio生态系统的一部分,专注于提供高效可靠的异步信号处理能力。


1 回复

Rust异步信号处理库compio-signal使用指南

简介

compio-signal是一个Rust异步信号处理库,提供高性能的异步信号捕获与处理功能。它基于compio运行时构建,允许开发者在异步上下文中高效地监听和处理Unix信号。

主要特性

  • 异步信号监听
  • 高性能信号处理
  • 与主流异步运行时兼容
  • 线程安全的信号处理

安装

在Cargo.toml中添加依赖:

[dependencies]
compio-signal = "0.2"
tokio = { version = "1.0", features = ["full"] }  # 或其他异步运行时

基本用法

监听单个信号

use compio_signal::Signal;

#[tokio::main]
async fn main() {
    // 创建一个监听SIGINT(CTRL+C)信号的Signal实例
    let signal = Signal::new(libc::SIGINT).unwrap();
    
    println!("Waiting for SIGINT (Ctrl+C)...");
    // 异步等待信号
    signal.wait().await;
    
    println!("SIGINT received, exiting...");
}

监听多个信号

use compio_signal::{Signal, Signals};

#[tokio::main]
async fn main() {
    // 创建一个同时监听SIGINT和SIGTERM的Signals实例
    let signals = Signals::new(&[libc::SIGINT, libc::SIGTERM]).unwrap();
    
    println!("Waiting for SIGINT or SIGTERM...");
    // 异步等待任一信号,返回接收到的信号值
    let signum = signals.wait().await;
    
    println!("Signal {} received, exiting...", signum);
}

高级用法

与任务取消结合使用

use compio_signal::Signal;
use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
    // 创建SIGINT信号监听器
    let signal = Signal::new(libc::SIGINT).unwrap();
    
    // 使用select!宏同时等待信号或超时
    tokio::select! {
        _ = signal.wait() => {
            println!("Received SIGINT, cancelling operation");
        },
        _ = sleep(Duration::from_secs(5)) => {
            println!("Operation completed successfully");
        }
    }
}

在Web服务器中使用

use compio_signal::Signal;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};
use std::convert::Infallible;

// 简单的请求处理函数
async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
    Ok(Response::new(Body::from("Hello World")))
}

#[tokio::main]
async fn main() {
    // 创建SIGTERM信号监听器
    let signal = Signal::new(libc::SIGTERM).unwrap();
    
    // 创建HTTP服务
    let make_svc = make_service_fn(|_conn| async {
        Ok::<_, Infallible>(service_fn(handle))
    });
    
    // 启动服务器并设置优雅关闭
    let server = Server::bind(&"127.0.0.1:3000".parse().unwrap())
        .serve(make_svc)
        .with_graceful_shutdown(async {
            signal.wait().await;
            println!("Received SIGTERM, shutting down gracefully...");
        });
    
    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}

完整示例代码

下面是一个结合多个功能的完整示例,展示如何在实际应用中使用compio-signal:

use compio_signal::{Signal, Signals};
use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
    println!("Signal handling demo starting...");
    
    // 监听多个信号
    let signals = Signals::new(&[libc::SIGINT, libc::SIGTERM, libc::SIGUSR1]).unwrap();
    
    // 模拟长时间运行的任务
    let long_running_task = async {
        println!("Long running task started...");
        for i in 1..=10 {
            println!("Task progress: {}/10", i);
            sleep(Duration::from_secs(1)).await;
        }
        println!("Task completed successfully");
    };
    
    // 使用select!同时等待信号或任务完成
    tokio::select! {
        signum = signals.wait() => {
            match signum {
                libc::SIGINT => println!("Received SIGINT (Ctrl+C), exiting..."),
                libc::SIGTERM => println!("Received SIGTERM, shutting down..."),
                libc::SIGUSR1 => println!("Received SIGUSR1, performing custom action..."),
                _ => println!("Received unknown signal: {}", signum),
            }
        },
        _ = long_running_task => {
            println!("All tasks completed normally");
        }
    }
    
    println!("Cleaning up resources...");
    // 这里可以添加资源清理代码
    println!("Application exited gracefully");
}

注意事项

  1. compio-signal目前主要支持Unix-like系统
  2. 某些信号可能无法被捕获(如SIGKILL)
  3. 在处理信号时应尽量减少耗时操作
  4. 信号处理函数中应避免使用非异步安全的操作

性能建议

  1. 对于高频信号,考虑使用批处理模式
  2. 避免在信号处理中执行阻塞操作
  3. 对于需要处理多个信号的场景,使用Signals而不是多个Signal实例

支持的信号列表

compio-signal支持所有标准Unix信号,常用信号包括:

  • SIGINT (2): 终端中断(Ctrl+C)
  • SIGTERM (15): 终止信号
  • SIGQUIT (3): 终端退出
  • SIGHUP (1): 终端挂起
  • SIGUSR1 (10): 用户自定义信号1
  • SIGUSR2 (12): 用户自定义信号2

通过compio-signal,开发者可以构建更健壮的异步应用,优雅地处理系统信号,实现平滑的关闭和重新加载功能。

回到顶部