7.3 KiB
7.3 KiB
DroneScrewServer 20分钟崩溃 - 最终调试版本
🔍 当前状态
已确认的信息
- ✅ PNG 崩溃已解决 - 禁用 PNG 压缩后不再有 PNG 相关崩溃
- ✅ 信号处理器已注册 - 但崩溃时没有触发
- ❌ 程序仍然在 20 分钟后崩溃 - 退出码 255
- ❌ 没有任何异常日志 - 所有 try-catch 未触发
- ❌ 没有信号日志 - signalHandler 未被调用
最新发现
崩溃时的最后日志:
[DETECT] frame #2163 after rawImageReady emit
[DETECT] frame #2163 before algo Detect, left=2242 right=19
[DETECT] frame #2163 after algo Detect, boxes=0
Main process exited, status=255/EXCEPTION
关键发现:
- ✅
after algo Detect日志完成 - ❌ 没有
after detectionResult emit日志 - ❌ 没有信号处理器日志
结论:崩溃发生在 emit detectionResult(result) 这一行,但不是通过信号触发的!
🎯 新增的调试功能(v3)
1. atexit 处理器
目的:捕获正常退出(通过 exit() 或 return)
功能:
- 程序退出时自动调用
- 打印完整的退出调用栈
- 告诉我们是谁调用了 exit()
预期日志:
[ATEXIT] Program is exiting normally!
[ATEXIT-BACKTRACE] Exit call stack (N frames):
[0] atexitHandler+0x...
[1] exit+0x...
[2] 某个函数+0x... ← 这就是罪魁祸首!
2. 检测线程详细日志
新增日志点:
emit detectionResult(result);
LOG_DEBUG("[DETECT] frame #%d after detectionResult emit\n", ...); ← 新增
...
LOG_DEBUG("[DETECT] frame #%d loop end, checking exit flag=%d\n", ...); ← 新增
目的:
- 确认是否是
emit detectionResult导致崩溃 - 检查循环是否正常继续
- 监控线程退出标志
🧪 测试步骤
1. 编译部署新版本
cd GrabBagPrj
qmake GrabBagPrj.pro
make
# 部署到设备
scp App/DroneScrewbolt/DroneScrewServer/DroneScrewServer user@device:/path/to/
2. 运行测试
# 重启服务
sudo systemctl restart dronescrewserver
# 实时查看日志
sudo journalctl -u dronescrewserver.service -f | tee /tmp/dronescrew_test.log
3. 等待崩溃(约 20 分钟)
4. 分析日志
查找关键日志:
# 1. 查找 atexit 日志
grep -A 30 "\[ATEXIT\]" /tmp/dronescrew_test.log
# 2. 查找信号日志
grep -A 30 "\[SIGNAL\]" /tmp/dronescrew_test.log
# 3. 查找崩溃前的最后日志
grep -B 20 "Main process exited" /tmp/dronescrew_test.log
📊 预期结果分析
场景 A:看到 atexit 日志
[DETECT] frame #2163 after algo Detect, boxes=0
[ATEXIT] Program is exiting normally!
[ATEXIT-BACKTRACE] Exit call stack (15 frames):
[0] atexitHandler+0x123
[1] __run_exit_handlers+0x456
[2] exit+0x789
[3] QCoreApplication::exit+0xabc ← Qt 事件循环退出
[4] 某个槽函数+0xdef
说明:
- 有代码主动调用了
exit()或QCoreApplication::exit() - 调用栈会告诉我们是哪个函数
可能的原因:
publishDetectionResult中某处调用了 exit- Qt 信号槽机制触发了某个会退出的代码
- 第三方库内部调用了 exit
场景 B:看到信号日志
[DETECT] frame #2163 after algo Detect, boxes=0
[SIGNAL] Caught signal 11: SIGSEGV (Segmentation Fault)
[BACKTRACE] Stack trace (20 frames):
[0] signalHandler+0x123
[1] /lib/libc.so+0x456
[2] 某个函数+0x789 ← 崩溃点
说明:
- 是信号导致的崩溃(段错误、总线错误等)
- 但之前的测试没有捕获到,可能之前版本没有正确注册
场景 C:既没有 atexit 也没有 signal
[DETECT] frame #2163 after algo Detect, boxes=0
Main process exited, status=255/EXCEPTION
说明:
- 程序被外部强制终止(
_exit()或kill) _exit()不会触发 atexit 处理器- 需要使用其他方法调试
下一步:
- 使用
strace跟踪系统调用 - 检查是否有其他进程杀死了这个进程
- 检查 systemd 的 cgroup 限制
场景 D:看到 "after detectionResult emit"
[DETECT] frame #2163 after algo Detect, boxes=0
[DETECT] frame #2163 after detectionResult emit ← 新日志
[DETECT] frame #2163 loop end, checking exit flag=0
[DETECT] frame #2164 before rawImageReady emit
(崩溃在其他地方)
说明:
emit detectionResult不是直接原因- 崩溃发生在后续的某个地方
- 需要继续增加日志
🔬 根据测试结果的下一步方案
如果有 atexit 日志
→ 根据调用栈定位调用 exit 的代码 → 修复或注释掉那个 exit 调用 → 问题解决
如果有 signal 日志
→ 根据调用栈定位崩溃的函数 → 修复段错误或内存问题 → 问题解决
如果都没有
→ 使用 strace 跟踪系统调用:
sudo strace -f -tt -T -o /tmp/strace.log \
-e trace=exit,exit_group,kill,tkill,tgkill \
/path/to/DroneScrewServer
→ 查看是否有外部进程杀死:
# 查看系统日志
dmesg | grep -i "killed\|oom"
# 查看 audit 日志
sudo ausearch -m ANOM_ABEND -ts recent
→ 检查 cgroup 限制:
systemctl show dronescrewserver.service | grep -i "memory\|cpu\|tasks"
🎯 最可能的原因(基于当前信息)
可能性 1:Qt 信号槽机制问题(60%)
detectionResult 信号通过 Qt::AutoConnection 从检测线程发送到主线程的槽函数。可能:
- Qt 的事件队列满了导致崩溃
- 跨线程信号槽的内部问题
- 槽函数中有问题的代码
验证方法:改用 Qt::QueuedConnection 明确指定队列连接
可能性 2:publishDetectionResult 内部问题(30%)
虽然有异常保护,但可能:
- ZeroMQ 内部调用了
_exit() - QJsonDocument 序列化时崩溃
- 互斥锁死锁导致问题
验证方法:临时注释掉整个函数体,看是否还崩溃
可能性 3:第三方库的定时任务(10%)
MVS SDK 或其他库的后台线程在 20 分钟后执行某个操作导致崩溃。
验证方法:使用 strace 或 gdb 附加到进程
📝 修改文件清单
本次修改(v3)
-
main.cpp- 增加
atexitHandler()- 捕获正常退出 - 注册
atexit()处理器
- 增加
-
DroneScrewServerPresenter.cpp- 增加
after detectionResult emit日志 - 增加
loop end日志
- 增加
累计修改
| 文件 | 修改内容 | 版本 |
|---|---|---|
DroneScrewZmqProtocol.cpp |
禁用 PNG 压缩 | v1 |
DroneScrewServerPresenter.cpp |
详细检测日志 | v1 |
DroneScrewZmqProtocol.cpp |
PNG/ZMQ 日志 | v1 |
main.cpp |
信号处理器 | v2 |
main.cpp |
atexit 处理器 | v3 ⭐ |
DroneScrewServerPresenter.cpp |
emit 后日志 | v3 ⭐ |
🚀 立即行动
- ✅ 编译部署 v3 版本
- ✅ 运行测试 至少 30 分钟
- ✅ 查找关键字:
[ATEXIT]- 正常退出[SIGNAL]- 信号崩溃after detectionResult emit- emit 是否完成
- ✅ 提供完整日志
💪 我们越来越接近真相了!
通过 atexit 处理器,我们一定能找到是谁调用了 exit()!
如果程序是被外部强制终止的(_exit() 或 kill),atexit 也不会触发,那时我们就知道要往那个方向调查了。
请尽快测试并提供新日志! 🎯