tokio-rs/axum

Deadlock when using same shared state in handler and middleware

Closed this issue · 0 comments

  • [ X] I have looked for existing issues (including closed) about this

Bug Report

Version

??? axum v0.7.4
? ??? axum-core v0.4.3

Platform

Windows 10 64-bit

Description

When I use shared state wrapped in Arc<RwLock> and use it in handler and middleware same time, I got deadlock

Example:

use std::sync::Arc;

use axum::{
    extract::{Request, State},
    middleware::{from_fn_with_state, Next},
    response::Response,
    routing::get,
    Router,
};
use tokio::sync::RwLock;

#[derive(Debug, Clone)]
struct AppData {
    pub title: String,
}

#[derive(Debug, Clone)]
struct AppState {
    data: Arc<RwLock<AppData>>,
}

async fn handler_with_state(State(state): State<AppState>) -> &'static str {
    let data = state.data.write().await;
    "Handler result"
}

async fn middleware_with_state(
    State(state): State<AppState>,
    request: Request,
    next: Next,
) -> Response {
    let data = state.data.read().await;
    let response = next.run(request).await;
    response
}

#[tokio::main]
async fn main() {
    let state = AppState {
        data: Arc::new(RwLock::new(AppData {
            title: "App title".to_owned(),
        })),
    };
    let app = Router::new()
        .route("/", get(handler_with_state))
        .route_layer(from_fn_with_state(state.clone(), middleware_with_state))
        .with_state(state);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}