You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中实现可中断睡眠 解决休眠无法响应SIGINT信号问题

Rust 可中断休眠实现方案

原生标准库实现思路

Rust 标准库没有直接提供可被信号中断的休眠接口,但可以通过std::sync::Condvar(条件变量)搭配原子状态标记实现需求,核心逻辑是将固定时长的休眠替换为带超时的条件变量等待,收到中断信号时主动唤醒等待流程即可。
示例代码如下:

use std::sync::{Arc, Condvar, Mutex};
use std::time::Duration;

fn main() {
    // 定义终止状态元组:(是否触发终止, 条件变量)
    let terminate_flag = Arc::new((Mutex::new(false), Condvar::new()));
    let flag_clone = terminate_flag.clone();

    // 注册ctrlc中断处理逻辑
    ctrlc::set_handler(move || {
        let (lock, cvar) = &*flag_clone;
        let mut terminate = lock.lock().unwrap();
        *terminate = true;
        // 唤醒所有等待条件变量的线程
        cvar.notify_all();
    }).expect("中断信号处理器注册失败");

    let (lock, cvar) = &*terminate_flag;
    loop {
        // 此处替换为你需要定期执行的业务逻辑
        println!("执行定时操作");

        // 带超时的条件等待:最长等待2秒,收到终止信号时直接唤醒
        let (lock_result, timeout_result) = cvar
            .wait_timeout_while(
                lock.lock().unwrap(),
                Duration::from_secs(2),
                |&mut should_terminate| !should_terminate
            )
            .unwrap();

        // 检查是否触发终止信号,是则直接退出循环
        if *lock_result {
            println!("收到中断信号,程序退出");
            break;
        }
    }
}

注意:Condvar 本身存在虚假唤醒的特性,上述实现通过wait_timeout_while的状态判断逻辑自动规避了该问题,不需要额外处理边界情况。

std::thread::sleep不可中断的原因

Rust 的sleep实现和C语言的sleep行为不同:C语言的sleep在被信号中断时会直接返回剩余休眠时长,上层可以感知到中断事件;而Rust标准库的sleep在底层系统调用返回EINTR(被信号中断)错误时,会自动计算剩余休眠时长并重试系统调用,所以上层逻辑感知不到中断,会一直休眠到总时长达标才返回。

其他可选实现方案

  • 如果项目使用Tokio等异步运行时,可以直接用tokio::time::sleep和信号监听Future搭配select!宏实现中断休眠,代码逻辑会更简洁。

内容的提问来源于stack exchange,提问作者Eolien55

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 13:36:04