IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Deadlock detection must not run as tokio task

    金庆发表于 2022-04-24 06:04:00
    love 0

    deadlock detection must not run as tokio task

    (Jin Qing's Column, Feb., 2022)

    parking_lot has an experimental feature: deadlock_detection.

    See: https://amanieu.github.io/parking_lot/parking_lot/deadlock/index.html

    use std::thread;
    use std::time::Duration;
    use parking_lot::deadlock;
    // Create a background thread which checks for deadlocks every 10s
    thread::spawn(move || {
    loop {
    thread::sleep(Duration::from_secs(10));
    let deadlocks = deadlock::check_deadlock();
    if deadlocks.is_empty() {
    continue;
    }
    println!("{} deadlocks detected", deadlocks.len());
    for (i, threads) in deadlocks.iter().enumerate() {
    println!("Deadlock #{}", i);
    for t in threads {
    println!("Thread Id {:#?}", t.thread_id());
    println!("{:#?}", t.backtrace());
    }
    }
    }
    });
    
    

    The output is like this:

    1 deadlocks detected
    Deadlock #0
    Thread Id 16072
    0: 0x7ff985cb659d - backtrace::backtrace::dbghelp::trace
    at d:\Users\jinqing\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.63\src\backtrace\dbghelp.rs:98
    ...
    13: 0x7ff985ae92f3 - lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock,cgc::scene_template::SceneTemplate>::read<parking_lot::raw_rwlock::RawRwLock,cgc::scene_template::SceneTemplate>
    at d:\Users\jinqing\.cargo\registry\src\github.com-1ecc6299db9ec823\lock_api-0.4.6\src\rwlock.rs:448
    14: 0x7ff985aeadf3 - cgc::scene::SceneData::check_body_collide
    at E:\gitlab\yserver\gc\src\scene.rs:99
    ...
    81: 0x7ff9f29b7034 - BaseThreadInitThunk
    82: 0x7ff9f2b02651 - RtlUserThreadStart
    
    

    But the deadlock detection thread can not be changed to a tokio task, because if deadlock happens, all tasks may be blocked, including the deadlock detection, causing no deadlock error output.

    In the following example, if the number of the deadlock tasks is larger than the thread number of tokio runtime, all tasks will be blocked.

    use std::{thread, time::Duration};
    use parking_lot::RwLock;
    use tokio::time;
    #[tokio::main]
    async fn main() {
    tokio::spawn(async move {
    for i in 0..999999 {
    println!("{}", i);
    time::sleep(Duration::from_secs(1)).await;
    }
    });
    const MAX: i32 = 100;
    for _ in 0..MAX {
    tokio::spawn(async move {
    {
    // DEADLOCK!
    let a = RwLock::new(());
    let _g1 = a.write();
    let _g2 = a.write();
    }
    time::sleep(Duration::from_secs(9999)).await;
    });
    }
    println!("Hello, world!");
    thread::sleep(Duration::from_secs(10));
    }
    
    

    The output is:

    0
    Hello, world!
    _
    
    

    If no deadlock, or the number of deadlock tasks is small, the output should be:

    0
    Hello, world!
    1
    2
    3
    ...
    
    


    金庆 2022-04-24 14:04 发表评论


沪ICP备19023445号-2号
友情链接