Home > Mobile >  How do I perform interruptible sleep in Rust?
How do I perform interruptible sleep in Rust?

Time:11-27

I am writing a Rust program that does an action every 2 seconds. The program also uses the ctrlc crate to handle interrupts. However, in some cases, I have to wait up to 2 secs when killing the process. I am using the default std::thread::sleep function, which I seemingly cannot interrupt.

Here comes my question. Is it possible for me to make my program sleep in an interruptible way? In other words, does Rust have a default feature for interrupting a sleeping program? I know that C automatically interrupts any sleep function when the SIGINT signal is received.

CodePudding user response:

Your signal handler needs to either make the running threads somehow stop or exit the process upon catching the signal.

Exitting the process is simple: call std::process::exit() in the signal handler after your cleanup is done.

Forwarding the signal to your sleeping threads is harder, you might be able to do that by setting some flag in an Arc<AtomicBool> upon catching SIGINT and repeatedly check that flag with shorter intermittent sleeps in between checks instead of a single longer sleep.

You could also come up with a solution based on channels where your ctrlc handler communicates with the running threads through a broadcast channel and waits for them to respond with some kind of done message before exitting the process. This done message could be through the sending end of a channel that the shutdown handler passes to the running thread. It could then wait with a timeout before force-quitting with std::process::exit.

CodePudding user response:

If you only want to cleanup and exit, then you can just call std::process::exit in the signal handler as suggested by the other answer. However if you want your threads to stop so that your application can proceed to some other task, you can use a channel and recv_timeout to get an interruptible sleep:

use std::thread;
use std::time::Duration;
use std::sync::mpsc;

let (send, recv) = mpsc::channel();

thread::spawn(move || {
    // When you want to sleep
    if let Ok(_) = recv.recv_timeout (Duration::from_secs (2)) {
        // Sleep was interrupted
        return;
    }
    // Slept for 2s, proceeding
});

// And elsewhere when you want to interrupt the thread:
send.send(());
  • Related