You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:22:59