金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  423 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks

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
...

posted on 2022-04-24 14:04 金庆 阅读(113) 评论(0)  编辑 收藏 引用 所属分类: 8. Rust

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理