I'm trying to programmatically listen to multiple signals and a ticking interval. To clear things up, here is the code I have currently:
use std::time::Duration;
use tokio::signal::unix::SignalKind;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut interval = tokio::time::interval(Duration::from_secs(5));
let sigrtmin = libc::SIGRTMIN();
let program_name = std::env::args().next().unwrap();
println!(
"Try executing this command:\nkill -{} $(pidof {})\n",
sigrtmin + 2,
program_name
);
let mut signal0 = tokio::signal::unix::signal(SignalKind::from_raw(sigrtmin))?;
let mut signal1 = tokio::signal::unix::signal(SignalKind::from_raw(sigrtmin + 1))?;
let mut signal2 = tokio::signal::unix::signal(SignalKind::from_raw(sigrtmin + 2))?;
let mut signal3 = tokio::signal::unix::signal(SignalKind::from_raw(sigrtmin + 3))?;
loop {
tokio::select! {
_ = signal0.recv() => {
println!("Got signal 0.");
}
_ = signal1.recv() => {
println!("Got signal 1.");
}
_ = signal2.recv() => {
println!("Got signal 2.");
}
_ = signal3.recv() => {
println!("Got signal 3.");
}
_ = interval.tick() => {
println!("Tick.");
}
}
}
}
So far, so good. But I just can't figure out how to programmatically (e.g. with a loop or a .collect()) create new signals and listen for them in the select!.
How would I go about doing that?
In this kind of situation, I tend to reach for channels, because
timeouton the receiving end.That being said, they're probably not the most elegant or efficient solution. A clean solution would probably use
futures::stream::select_allandtokio_stream::wrappers::SignalStream, see comments on the question. But that's a bit more difficult to understand and set up.Anyway, the following might work:
If you want to treat more different kinds of events, you'll have to define yourself an enum to be sent over the channel.