gpt4 book ai didi

multithreading - 使用多线程python扩展调试多线程程序时GDB挂起

转载 作者:行者123 更新时间:2023-12-01 13:48:53 26 4
gpt4 key购买 nike

我正在尝试开发一个 GDB python 扩展,它定义了一个启动新线程的命令,用户可以在其中检查任意类型的变量。我的 python 扩展的框架是这样的:

import gdb
import threading

def plot_thread():
import time
while True:
print('Placeholder for a window event loop.')
time.sleep(1)
pass
pass

class PlotterCommand(gdb.Command):
def __init__(self):
super(PlotterCommand, self).__init__("plot",
gdb.COMMAND_DATA,
gdb.COMPLETE_SYMBOL)
self.dont_repeat()
pass

def invoke(self, arg, from_tty):
plot_thread_instance=threading.Thread(target=plot_thread)
plot_thread_instance.daemon=True
plot_thread_instance.start()
pass

pass

PlotterCommand()

可以看出,我在这里定义了一个plot命令。当我尝试调试以下程序时,如果我执行以下操作,GDB 将挂起:

  1. 在 procedure() 线程内的任意位置放置一个断点(例如,while 循环内的第 9 行)。
  2. 在 gdb 遇到断点后运行命令 plot
  3. 之后运行continue
#include <iostream>
#include <thread>

using namespace std;

void procedure() {
cout << "before loop"<<endl;
while(1) {
cout << "loop iteration"<<endl;
}
}

int main() {
thread t(procedure);
t.join();
return 0;
}

最奇怪的是,如果我将此代码更改为在不启动线程的情况下调用 procedure(),GDB 永远不会挂起(占位符消息仍按我的预期打印)。

到目前为止,我已尝试使用 GDB 版本 7.5.1 和 7.10 运行此过程,但我总是遇到相同的行为。

我做错了什么? GDB 不支持守护线程吗?这似乎不符合 section 23.2.2.1 of the documentation 的内容建议:GDB 可能不是线程安全的,但我不认为它应该在启动这样一个愚蠢的守护线程后挂起。

最佳答案

来自 this blog post :

GDB uses this function (sigsuspend, the function where GDB hangs) to wait for new events from the application execution: when something occurs in the debuggee (see how debuggers work), the kernel will inform GDB of it by sending a SIGCHLD signal. When it's received, GDB awakes and check what happened.

However, the signal is delivered to GDB process, but not necessarily to its main thread. And it practise, it occurs often that it's delivered to the second thread, who doesn't care about it (that's the default behavior), and continues its life as if nothing occurred.

解决方案是配置线程信号处理行为,以便只有 GDB 主线程收到这些信号的通知:

import gdb
import threading
import pysigset, signal # Import these packages!

def plot_thread():
import time
while True:
print('Placeholder for a window event loop.')
time.sleep(1)
pass
pass

class PlotterCommand(gdb.Command):
def __init__(self):
super(PlotterCommand, self).__init__("plot",
gdb.COMMAND_DATA,
gdb.COMPLETE_SYMBOL)
self.dont_repeat()
pass

def invoke(self, arg, from_tty):
with pysigset.suspended_signals(signal.SIGCHLD): # Disable signals here!
plot_thread_instance=threading.Thread(target=plot_thread)
plot_thread_instance.daemon=True
plot_thread_instance.start()
pass
pass

pass

PlotterCommand()

pysigset 包是必需的,可以从 pip 安装(sudo pip install pysigset)。

关于multithreading - 使用多线程python扩展调试多线程程序时GDB挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33482870/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com