wxWidgets 3.2.1应用在CentOS 8.2随机挂起,关联Source ID报错
问题分析与解决方案
这个"Source ID xxxx was not found when attempting to remove it"错误是Linux下GTK+后端的典型问题,根源是GTK主循环尝试移除一个已失效的事件源(GSource)。结合你的架构和wxWidgets版本,以下是具体排查方向和修复建议:
核心原因
CentOS 8.2搭载的GTK+ 3.22存在一些线程事件交互的小bug,当跨线程投递事件时,如果目标窗口(你的Frame)已销毁、事件源被提前释放,或者事件投递频率过高,就会触发这个错误,进而导致程序挂起。
具体修复步骤
1. 严格管控窗口生命周期与事件投递的合法性
在网络线程发送事件前,必须确保目标Frame仍然存活:
// 在网络线程中发送事件前添加检查 if (parent && parent->IsAlive()) { wxThreadEvent event(wxEVT_THREAD, ID_ProcClientCmd); event.SetPayload(pkt_info); wxQueueEvent(parent, event.Clone()); }
同时,在Frame的析构函数中,要主动通知网络线程停止发送事件——比如设置一个原子布尔变量m_stopThread,网络线程循环中持续检查该变量,一旦为true就终止事件投递并退出。
2. 调整事件投递方式
尝试将wxQueueEvent替换为wxPostEvent,两者都是线程安全的异步事件投递,但内部实现与GTK主循环的交互逻辑不同:
// 替换后的代码 if (parent && parent->IsAlive()) { wxThreadEvent event(wxEVT_THREAD, ID_ProcClientCmd); event.SetPayload(pkt_info); wxPostEvent(parent, event); }
wxPostEvent会直接将事件放入GUI线程的事件队列,避免wxQueueEvent可能带来的额外GSource注册/销毁操作,降低触发GTK bug的概率。
3. 检查Payload的内存安全性
确保pkt_info的内存生命周期覆盖事件处理的全程:
- 如果是动态分配的对象,改用
std::shared_ptr封装后再设置Payload,避免事件处理时内存已被释放:
auto pkt_ptr = std::make_shared<PktInfo>(...); event.SetPayload(pkt_ptr);
- 在GUI线程的事件处理函数中,正确提取并管理Payload的生命周期。
4. 启用GTK调试日志定位根源
如果以上方法仍未解决,设置GTK的调试环境变量,获取更详细的错误栈:
export G_MESSAGES_DEBUG=all ./your_app
运行后会输出GTK内部的调用日志,通过这些日志可以找到触发"Source ID not found"的具体操作,进而精准定位问题。
针对复现Demo的额外建议
- 在Demo中添加Frame销毁时的日志输出,确认错误是否发生在Frame关闭后仍有事件投递的场景。
- 尝试降低事件投递的频率,看是否能减少错误出现的概率,验证是否是高频率事件触发的GTK bug。
内容的提问来源于stack exchange,提问作者Yogi Wannabe
相关产品推荐
相关产品推荐

