简体   繁体   English

C++ 线程不会在 gdb 异步模式下使用用户定义或 python 命令序列停止

[英]C++ thread not stopping in gdb async mode using user-defined or python command sequence

I'm using gdb 7.4.1 on embedded powerpc target to perform some analysis on my multi-threaded C++ program that uses pthreads. My end goal is to script gdb with python to automate some common analysis functions.我在嵌入式 powerpc 目标上使用 gdb 7.4.1 对使用 pthreads 的多线程 C++ 程序执行一些分析。我的最终目标是使用 python 编写脚本 gdb 以自动执行一些常见的分析功能。 The problem is that I am finding some discrepancy in behavior when I run commands individually vs. in a gdb user-defined command (or invoking the same commands via python script).问题是,当我单独运行命令与在 gdb 用户定义的命令(或通过 python 脚本调用相同的命令)中运行命令时,我发现行为存在一些差异。

edit: I found this reference to a very similar problem on the main gdb mailing list.编辑:我在主要的 gdb 邮件列表上发现一个非常相似的问题。 Although I don't completely follow Pedro's response about the limitation of async mode, I think he's implying that in async mode, the relative timing of user-defined command sequences cannot be trusted.尽管我不完全遵循 Pedro 关于异步模式限制的回应,但我认为他是在暗示在异步模式下,用户定义的命令序列的相对时序是不可信任的。 This is what I found empirically.这是我凭经验发现的。

In both scenarios, I perform the following start-up steps, loading my program, setting its args, and turning on asynchronous and non-stop debugging modes, then running the program in the background:在这两种情况下,我都执行以下启动步骤,加载我的程序,设置它的参数,打开异步和不间断调试模式,然后在后台运行程序:

(gdb) file myprogram
(gdb) set args --interface=eth0 --try-count=0
(gdb) set target-async on
(gdb) set pagination off
(gdb) set non-stop on
(gdb) run &

At this point, if I manually issue interrupt and then info threads commands, I see the list of all threads running except one that got stopped.此时,如果我手动发出interruptinfo threads命令,我会看到除已停止的线程之外的所有正在运行的线程的列表。 Then I can continue & and repeat to my hearts content, it works consistently.然后我可以continue &并重复我的心满意足,它始终如一。 When stopped, I can inspect that thread's stack frames and all is well.停止时,我可以检查该线程的堆栈帧,一切正常。

However, if instead I put these commands into a user-defined gdb command:但是,如果我将这些命令放入用户定义的 gdb 命令中:

(gdb) define foo
(gdb) interrupt
(gdb) info threads
(gdb) continue &
(gdb) end
(gdb) foo
Cannot execute this command while the selected thread is running.

Then the thread list printed by foo indicates no threads were stopped, and so the continue & command returns Cannot execute this command while the selected thread is running.然后 foo 打印的线程列表表明没有线程被停止,因此continue &命令返回Cannot execute this command while the selected thread is running. . . I thought this was a problem inherent to the asynchronous gdb commanding, so I inserted an absurdly long wait after the interrupt command and got the same behavior:我认为这是异步 gdb 命令固有的问题,所以我在中断命令后插入了一个荒谬的漫长等待并得到了相同的行为:

(gdb) define foo
(gdb) interrupt
(gdb) shell sleep 5
(gdb) info threads
(gdb) continue &
(gdb) end
(gdb) foo
Cannot execute this command while the selected thread is running.

With or without the sleep command, I can always issue the manual CLI commands and the threads get stopped correctly.无论有没有 sleep 命令,我总是可以发出手动 CLI 命令并且线程得到正确停止。

Similarly, I get the same results sourcing a python script to do the thread perusal:类似地,我使用 python 脚本来细读线程,得到相同的结果:

import gdb, time

gdb.execute("file myprogram")
gdb.execute("set args --interface=eth0 --try-count=0")
gdb.execute("set target-async on")
gdb.execute("set pagination off") 
gdb.execute("set non-stop on")
gdb.execute("run &")
time.sleep(5)
gdb.execute("interrupt")

# here, I inspect threads via gdb module interface
# in practice, they're always all running bc the program neven got interrupted
for thread in gdb.selected_inferior().threads():
    print thread.is_running(),

gdb.execute("continue &")

I get the same result even if I specify from_tty=True in the gdb.execute calls.即使我在gdb.execute调用中指定from_tty=True ,我也会得到相同的结果。 Also, if I use continue -a it suppresses the error string but does not help otherwise bc the interrupt call still doesn't work.另外,如果我使用continue -a它会抑制错误字符串但无济于事,因为中断调用仍然不起作用。

So... is this:所以...是这样的:

  • cockpit error?驾驶舱错误? Is there something that I'm omitting or doing incorrectly, given what I'm trying to accomplish?考虑到我想要完成的事情,是否有我遗漏或做错的事情? Should this work, or do I have to use GDB/MI to asynchronously "drive" gdb like this?这应该有效,还是我必须使用 GDB/MI 像这样异步“驱动”gdb?
  • a timing problem?时间问题? Maybe invoking shell sleep (or python time.sleep() ) doesn't do what I assume it would, in this context.在这种情况下,调用shell sleep (或python time.sleep() )可能不会像我想象的那样。
  • problem with my usage of pthreads?我使用 pthreads 有问题吗? I have assumed that since using manual gdb commands always works correctly this is not the case.我假设因为使用手动 gdb 命令总是可以正常工作,所以事实并非如此。
  • a gdb problem? gdb 问题?

Thanks.谢谢。

I think this is most likely a gdb problem. 我认为这很可能是一个gdb问题。 I don't know enough about the inferior-control stuff to be more confident. 我不太了解劣质控制的东西更自信。 I do know that inferior control generally has not been wired up to Python... 我知道劣质控制通常没有连接到Python ...

One thing worth trying is having a separate Python thread that does the wait, then sends an "interrupt" command to the main gdb thread using gdb.post_event. 值得一试的是有一个单独的Python线程来执行等待,然后使用gdb.post_event向主gdb线程发送“interrupt”命令。

Then, instead of synchronously examining the threads or doing work after the "interrupt", instead use the gdb.events.stop event source to trigger your actions. 然后,不是在“中断”之后同步检查线程或执行工作,而是使用gdb.events.stop事件源来触发您的操作。

Please file bugs liberally about holes in the Python API. 请在Python API中大量提交漏洞。

I came across your post today and tested this gdb-python combination.我今天看到你的帖子并测试了这个 gdb-python 组合。 I found a way to make it works.我找到了让它工作的方法。

  1. Set an env in your terminal etc: setenv MY_ENV 1在您的终端等中设置环境:setenv MY_ENV 1
  2. In your C/C++ source code, you can add a few line near the start of the code to get the env: getenv(MY_ENV), and then print out the process id with get_pid()在您的 C/C++ 源代码中,您可以在代码开头附近添加几行以获取环境:getenv(MY_ENV),然后使用 get_pid() 打印出进程 ID
  3. Set the env in the terminal, then run the program.在终端中设置环境,然后运行程序。 The program will stop and show its process id on the screen.该程序将停止并在屏幕上显示其进程 ID。 say 1234说1234
  4. Write a separate gdb_monitor.py for gdb eg:为 gdb 写一个单独的 gdb_monitor.py 例如:
 import gdb
 # Your code
 gdb.execute("set target-async on")
 gdb.execute("set pagination off") 
 gdb.execute("set non-stop on")
 gdb.execute("set args --interface=eth0 --try-count=0")
 # Add these lines
 pid = input("Python script is running, attach the pid here:")
 gdb.execute("attach {}".format(pid))

while(1):
 print("I am running gdb in async mode, add the break condition here")
  1. Now in gdb, you can source the python script, enter the pid in the script.现在在gdb,可以source python脚本,在脚本中输入pid。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM