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. 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).
edit: I found this reference to a very similar problem on the main gdb mailing list. 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. 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. Then I can continue &
and repeat to my hearts content, it works consistently. 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) 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.
. 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) 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.
Similarly, I get the same results sourcing a python script to do the thread perusal:
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. Also, if I use continue -a
it suppresses the error string but does not help otherwise bc the interrupt call still doesn't work.
So... is this:
shell sleep
(or python time.sleep()
) doesn't do what I assume it would, in this context.Thanks.
I think this is most likely a gdb problem. 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...
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.
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.
Please file bugs liberally about holes in the Python API.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With