I thout that the loop would block the executor pool, and no other axum requests would be served, as the pool is stuck in the loop. In other words: The task will be holding the cpu until it .awaits something, or the function exits.
Either my assumption is incorrect, or is something else happening under the hood?
In my understandig it should just block the one thead of the thread pool in which the task is currently processed. all other thread should execute tasks normally.
I made a small test project, with the following dependencies:
axum = "0.7.4"
tokio = { version = "1.36.0", features = ["full"] }
use axum::response::IntoResponse;
use axum::{routing::get, Router};
async fn blocking_handler() {
println!("Blocking thead id: {:?}", std::thread::current().id());
loop {}
}
async fn hello_world() -> impl IntoResponse {
println!("Generic thread: {:?}", std::thread::current().id());
"Hello World"
}
async fn goodbye_world() -> impl IntoResponse {
println!("Generic thread 2: {:?}", std::thread::current().id());
"Goodbye World"
}
#[tokio::main]
async fn main() {
// build our application with a route
let app = Router::new()
.route("/", get(hello_world))
.route("/1", get(goodbye_world))
.route("/blocking", get(blocking_handler));
// run our app with hyper, listening globally on port 3000
let listener = tokio::net::TcpListener::bind("0.0.0.0:3331").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
I guess the important point here is that tokio runs with rt-multi-thread feature, so tokio uses threads (if available by the OS) to schedule tasks. I'd say if tokio was compiled to run with a single thread, the first request to the blocking handler will get the whole process stuck.