I have a UDP socket that is receiving data
pub async fn start() -> Result<(), std::io::Error> {
loop {
let mut data = vec![0; 1024];
socket.recv_from(&mut data).await?;
}
}
This code is currently blocked on the .await
when there is no data coming in. I want to gracefully shut down my server from my main thread, so how do I send a signal to this .await
that it should stop sleeping and shut down instead?
Note: The Tokio website has a page on graceful shutdown.
If you have more than one task to kill, you should use a broadcast channel to send shutdown messages. You can use it together with
tokio::select!
.Then to kill all the tasks, send a message on the channel.
To kill only a single task, you can use the
JoinHandle::abort
method, which will kill the task as soon as possible. Note that this method is available only in Tokio 1.x and 0.3.x, and to abort a task using Tokio 0.2.x, see the next section below.As an alternative to
JoinHandle::abort
, you can useabortable
from the futures crate. When you spawn the task, you do the following:Then later you can kill the task by calling the
abort
method.Of course, a channel with
select!
can also be used to kill a single task, perhaps combined with anoneshot
channel rather than a broadcast channel.All of these methods guarantee that the
real_start
method is killed at an.await
. It is not possible to kill the task while it is running code between two.await
s. You can read more about why this is here.The mini-redis project contains an accessible real-world example of graceful shutdown of a server. Additionally, the Tokio tutorial has chapters on both select and channels.