背景

有时候程序异常,陷入递归循环,出现很深的堆栈。碰到这种情况,gdb attch 上去一看,都是固定的几个函数循环,好像没有办法分析从哪陷入进去的,
怎么办?

如下面的堆栈所示:

80588 nvme_qpair_submit_request (qpair=qpair@entry=0x200000a071d8, req=0x200025bd03c0) at nvme_qpair.c:723
#80589 0x00000000009bc707 in spdk_nvme_ns_cmd_read (ns=0x20001f21db80, qpair=0x200000a071d8, buffer=<optimized out>, lba=<optimized out>, lba_count=<optimized out>, cb_fn=<optimized out>, cb_arg=<optimized out>,
    io_flags=<optimized out>) at nvme_ns_cmd.c:600
#80590 0x00000000005bf2c4 in kunlun::user_space_block_system::SpdkBlockSystem::DoReadBlock (this=0x3dbb580, c=0x7f203c00ef70) at /root/workspace/join/essd/libs/user-space-block-system/user_space_block_system.cc:1666
#80591 0x00000000005bf3a1 in kunlun::user_space_block_system::SpdkBlockSystem::Run (this=0x3dbb580, ctx=0x7f203c00ef70) at /root/workspace/join/essd/libs/user-space-block-system/user_space_block_system.cc:1682
#80592 0x00000000005bf86c in kunlun::user_space_block_system::SpdkBlockSystem::SubmitJob (this=0x3dbb580, ctx=0x7f203c00ef70) at /root/workspace/join/essd/libs/user-space-block-system/user_space_block_system.cc:1779
---Type <return> to continue, or q <return> to quit---
#80593 0x00000000005bf5e1 in kunlun::user_space_block_system::AsyncWork (c=0x7f203c00ef70) at /root/workspace/join/essd/libs/user-space-block-system/user_space_block_system.cc:1745
#80594 0x00000000009dc156 in _spdk_msg_queue_run_batch (max_msgs=<optimized out>, thread=0x3dbc140) at thread.c:433
#80595 spdk_thread_poll (thread=0x3dbc140, max_msgs=max_msgs@entry=0, now=now@entry=5360428740196990) at thread.c:506
#80596 0x0000000000991cc8 in _spdk_reactor_run (arg=0x3152500) at reactor.c:337
#80597 0x00000000009f02ef in eal_thread_loop ()
#80598 0x00007f209e659dc5 in start_thread () from /lib64/libpthread.so.0
#80599 0x00007f209d07721d in clone () from /lib64/libc.so.6


可以看到上面的堆栈深度有80599 层之多,那么怎么快速进入到堆栈的末尾呢?

解决方法

万能回车键

gdb attach 到异常的进程或者堆栈之后,按住回车键,一直不松手,持续1分钟,最后它就会到堆栈的最底层。(如果堆栈很深,这个时间需要长点)

二分法

gdb attach 到异常的进程或者堆栈之后,用二分法从frame 100000 开始,如果对应frame存在,则增大两倍,否则除以2,依次循环,直至找到期望的起始frame。