rust - 如何在异步函数中设置断点?
问题描述
我有一个带有async
我想调试的方法的结构。我使用 gdb 通过调试构建设置断点。async
以下是在方法处停止时代码的样子Strct::async_method
:
0x5555557f4a6a <bin::Strct::async_method+26> mov QWORD PTR [rsp+0x10],rsi
0x5555557f4a6f <bin::Strct::async_method+31> mov QWORD PTR [rsp+0x18],rdx
0x5555557f4a74 <bin::Strct::async_method+36> mov BYTE PTR [rsp+0x112],0x0
0x5555557f4a7c <bin::Strct::async_method+44> lea rsi,[rsp+0x10]
0x5555557f4a81 <bin::Strct::async_method+49> mov QWORD PTR [rsp+0x8],rax
0x5555557f4a86 <bin::Strct::async_method+54> call 0x5555557e6970 <core::future::from_generator>
代码调用core::future::from_generator
不是我想要调试的。async
暂停方法体执行的正确方法是什么?
解决方案
让我们用它作为我们的MRE
use futures::executor; // 0.3.5
pub fn exercise() {
executor::block_on(example());
}
#[inline(never)]
async fn example() {
canary()
}
#[inline(never)]
fn canary() {}
如果您查看此程序集,您将看到编译器如何实现异步函数。该async
函数返回一个 implementation 类型impl Future
,它由生成器在后台提供支持:
playground::example:
subq $24, %rsp
movb $0, 16(%rsp)
movzbl 16(%rsp), %edi
callq *core::future::from_generator@GOTPCREL(%rip)
movb %al, 23(%rsp)
movb 23(%rsp), %al
movb %al, 8(%rsp)
movb 8(%rsp), %al
addq $24, %rsp
retq
异步函数的实际主体被移动到生成器中,它恰好使用了名称{{closure}}
:
playground::example::{{closure}}:
;; Lots of instructions removed
movq playground::canary@GOTPCREL(%rip), %rcx
callq *%rcx
jmp .LBB20_2
;; Even more removed
因此,您可以在生成的函数上设置断点:
(lldb) br set -r '.*example.*closure.*'
(lldb) r
Process 28101 launched: '/tmp/f/target/debug/f' (x86_64)
Process 28101 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000ab0 f`f::example::_$u7b$$u7b$closure$u7d$$u7d$::h2b30ad777e7395f3((null)=(pointer = 0x00007ffeefbff328), (null)=ResumeTy @ 0x00007ffeefbff070) at main.rs:8:20
5 }
6
7 #[inline(never)]
-> 8 async fn example() {
9 canary()
10 }
11
Target 0: (f) stopped.
您还可以在所需的行上设置断点:
(lldb) breakpoint set --file /private/tmp/f/src/main.rs --line 9
(lldb) r
Process 28113 launched: '/tmp/f/target/debug/f' (x86_64)
Process 28113 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000ad8 f`f::example::_$u7b$$u7b$closure$u7d$$u7d$::h2b30ad777e7395f3((null)=(pointer = 0x00007ffeefbff328), (null)=ResumeTy @ 0x00007ffeefbff070) at main.rs:9:5
6
7 #[inline(never)]
8 async fn example() {
-> 9 canary()
10 }
11
12 #[inline(never)]
Target 0: (f) stopped.
也可以看看:
推荐阅读
- laravel - 从具有关系 Laravel 5.2 的查询中获取图像
- listview - 如何在 Xamarin Forms 的同一页面上创建水平和垂直列表视图?
- java - 如何创建一个等待用户按钮单击操作 3 秒的计时器,否则意图执行另一个活动?
- sql-server-2008 - 如何拆分/考虑每行中的 3 个字符
- app-store-connect - iTunes Connect 要求提供 6.5 英寸和 Apple Watch 屏幕截图
- angularjs - ng-bind-html 对复合变量表达式失败
- mysql - 使用子查询执行 SQL 多边形查询需要很长时间
- javascript - Npm 错误“错误:EACCES:权限被拒绝,mkdir '../node-sass/build'”
- javascript - 在 vue-chartjs 中循环遍历数组
- ruby-on-rails - 显示关联的模型对象字段