我正在尝试开发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将挂起:
#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不支持守护程序线程吗?这似乎与文档的23.2.2.1节所建议的不符:GDB可能不是线程安全的,但我认为在启动这样一个愚蠢的守护程序线程后,它不应挂起。
从这篇博客文章:
GDB使用此函数(sigsuspend,GDB挂起的函数)等待应用程序执行中的新事件:当调试对象中发生某些事件(请参阅调试器的工作原理)时,内核将通过发送SIGCHLD信号将其通知GDB。收到消息后,GDB醒来并检查发生了什么。
但是,信号被传递到GDB进程,但不一定传递到其主线程。实际上,它经常发生在传递给第二个线程时,该线程不关心它(这是默认行为),并且像没有发生任何事情一样继续其生命。
解决方案是配置线程信号处理行为,以便仅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被安装(须藤PIP安装pysigset)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句