GrabBag/App/DroneScrewbolt/DIAGNOSTIC_LOG_ENHANCEMENT.md
2026-06-26 17:55:15 +08:00

5.9 KiB
Raw Blame History

DroneScrewServer 崩溃诊断日志增强

📊 崩溃日志分析结果

问题复现

  • 运行时间: 约 19 分钟
  • 处理帧数: 约 2100+ 帧
  • 崩溃点: 处理第 1000 次检测帧后
  • 退出码: 255 (EXCEPTION)

关键发现

  1. 没有 C++ 异常日志

    • 已添加的 try-catch 没有捕获到任何异常
    • 说明崩溃不是由可捕获的 C++ 异常引起
  2. 内存监控失败

    [HEARTBEAT] rss=N/A vmPeak=N/A vmSize=N/A threads=N/A
    
    • /proc/self/status 读取失败
    • 无法通过心跳日志监控内存增长
  3. 检测线程挂起

    • 最后日志:[PUB-raw] #1000 frame=2244
    • 5 秒后程序崩溃
    • 检测线程在第 1000 帧后没有新的日志输出

怀疑根因

1. PNG 压缩导致卡死(最可能)

  • 4096x3000 双目图像 PNG 压缩非常消耗 CPU
  • 可能导致:
    • 内存耗尽 - 压缩过程中申请大量临时内存
    • 线程阻塞 - 压缩时间过长
    • 超时死锁 - 与其他线程竞争资源

2. ZeroMQ 发布阻塞

  • 发布 10MB+ 数据包可能导致阻塞
  • 如果接收端处理不及时,发送端卡住

3. 算法库段错误

  • Stub 算法库可能有内存访问错误
  • 段错误无法被 try-catch 捕获

🔍 新增诊断日志

1. 检测线程详细日志

位置: DroneScrewServerPresenter.cpp::detectThreadFunc()

// 原始图像发布前后
LOG_DEBUG("[DETECT] frame #%d before rawImageReady emit, left=%llu right=%llu\n", ...);
emit rawImageReady(leftImg, rightImg);
LOG_DEBUG("[DETECT] frame #%d after rawImageReady emit\n", ...);

// 算法调用前后
LOG_DEBUG("[DETECT] frame #%d before algo Detect, left=%llu right=%llu\n", ...);
m_pAlgo->Detect(inLeft, inRight, result);
LOG_DEBUG("[DETECT] frame #%d after algo Detect, boxes=%zu\n", ...);

目的:精确定位崩溃发生在哪个步骤

2. PNG 编码日志

位置: DroneScrewZmqProtocol.cpp::publishRawImage()

LOG_DEBUG("[PUB-raw] enter frame=%llu left=%ux%u right=%ux%u\n", ...);
LOG_DEBUG("[PUB-raw] before PNG encode frame=%llu\n", ...);
// PNG 压缩
LOG_DEBUG("[PUB-raw] after PNG encode frame=%llu usePng=%d leftSize=%zu rightSize=%zu\n", ...);

目的:监控 PNG 压缩耗时和是否卡死

3. ZeroMQ 发布日志

位置: DroneScrewZmqProtocol.cpp::publishRawImage()

LOG_DEBUG("[PUB-raw] before ZMQ publish frame=%llu payloadSize=%d\n", ...);
const int ret = m_pZmqRawPublisher->Publish(...);
LOG_DEBUG("[PUB-raw] after ZMQ publish frame=%llu ret=%d\n", ...);
LOG_DEBUG("[PUB-raw] exit frame=%llu\n", ...);

目的:监控 ZeroMQ 发布是否阻塞

🧪 测试步骤

1. 重新编译部署

cd GrabBagPrj
qmake GrabBagPrj.pro
make
# 部署到设备

2. 运行测试(至少 30 分钟)

sudo systemctl restart dronescrewserver
sudo journalctl -u dronescrewserver.service -f

3. 分析新日志

场景 A: PNG 编码卡死

[DETECT] frame #1001 before rawImageReady emit, left=xxx right=xxx
[PUB-raw] enter frame=xxx
[PUB-raw] before PNG encode frame=xxx
(没有 after PNG encode 日志) → PNG 压缩时卡死

解决方案

  • 关闭 PNG 压缩,改用原始格式
  • 降低图像分辨率
  • 使用更快的压缩库

场景 B: ZeroMQ 发布阻塞

[PUB-raw] after PNG encode frame=xxx usePng=1 leftSize=xxx rightSize=xxx
[PUB-raw] before ZMQ publish frame=xxx payloadSize=xxx
(没有 after ZMQ publish 日志) → ZeroMQ 发布时阻塞

解决方案

  • 设置 ZeroMQ 发送超时
  • 使用非阻塞模式
  • 限制发送队列大小

场景 C: 算法库段错误

[DETECT] frame #1001 after rawImageReady emit
[DETECT] frame #1001 before algo Detect, left=xxx right=xxx
(没有 after algo Detect 日志) → 算法调用时崩溃

解决方案

  • 检查算法库实现
  • 验证输入数据有效性
  • 使用 gdb 或 coredump 定位

场景 D: emit detectionResult 阻塞

[DETECT] frame #1001 after algo Detect, boxes=0
(没有后续日志) → Qt 信号槽处理时阻塞

解决方案

  • 检查 slot 函数实现
  • 确认信号槽连接方式Qt::DirectConnection 可能阻塞)

📈 预期日志输出

正常流程(每 100 帧)

[DETECT] frame #100 before rawImageReady emit, left=xxx right=xxx
[PUB-raw] enter frame=xxx left=4096x3000 right=4096x3000
[PUB-raw] before PNG encode frame=xxx
[PUB-raw] after PNG encode frame=xxx usePng=1 leftSize=2000000 rightSize=2000000
[PUB-raw] before ZMQ publish frame=xxx payloadSize=4000088
[PUB-raw] after ZMQ publish frame=xxx ret=0
[PUB-raw] #100 frame=xxx compression=png left=4096x3000 right=4096x3000 payload=4000088
[PUB-raw] exit frame=xxx
[DETECT] frame #100 after rawImageReady emit
[DETECT] frame #100 before algo Detect, left=xxx right=xxx
[DETECT] frame #100 after algo Detect, boxes=0
[DETECT] frame #100 id=xxx rawPub=1 boxes=0

崩溃前的最后日志

查看崩溃前最后一条带有 [DETECT][PUB-raw] 的日志,就能知道卡在哪里。

🔧 后续优化建议

根据测试结果,可能需要:

  1. 关闭 PNG 压缩(如果 PNG 编码卡死)

    • 修改 encodeImagePng 直接返回 false
    • 使用原始格式传输
  2. 异步发布(如果 ZeroMQ 阻塞)

    • 将 ZeroMQ 发布放到独立线程
    • 使用队列缓存待发布的数据
  3. 限制发布频率(如果性能不足)

    • 每 N 帧发布一次原始图像
    • 降低图像分辨率
  4. 修复算法库(如果算法崩溃)

    • 联系算法提供方
    • 增加输入数据验证

📝 修改文件清单

  1. App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.cpp

    • detectThreadFunc() - 增加检测流程各阶段日志
  2. App/DroneScrewbolt/DroneScrewServer/DroneScrewZmqProtocol.cpp

    • publishRawImage() - 增加 PNG 编码和 ZeroMQ 发布日志
  3. App/DroneScrewbolt/DIAGNOSTIC_LOG_ENHANCEMENT.md - 本文档