# DroneScrewServer 崩溃问题完整解决方案 ## 📊 问题总结 ### 问题 1:PNG 编码崩溃 ✅ 已解决 **现象**: - 程序在检测模式下运行约 19 分钟后崩溃 - 崩溃发生在 PNG 编码过程中 - 日志显示:`[PUB-raw] before PNG encode` → 崩溃 **根本原因**: - PNG 编码库在 ARM 平台处理 4096x3000 大图像时发生段错误 - OpenCV 或 libpng 的内部问题 **解决方案**: - 禁用 PNG 压缩,使用原始格式传输 - 文件:`DroneScrewZmqProtocol.cpp` - 修改:强制 `usePng = false` **影响**: - ✅ PNG 崩溃已完全解决 - ⚠️ 网络带宽从 ~10MB/帧 增加到 ~24MB/帧 - ✅ 千兆局域网完全足够(占用 38% 带宽) --- ### 问题 2:20 分钟定时崩溃 🔍 调查中 **现象**: - 禁用 PNG 后,程序仍然在约 20 分钟后崩溃 - **Idle 模式(完全空载)也崩溃** - 没有任何异常日志或错误信息 - 退出码:255 **测试记录**: 1. **第一次崩溃(01:44:59)**: - 运行时长:约 20 分钟 - 模式:检测模式(处理了 2041 帧) - 最后日志:`[DETECT] frame #2041 after algo Detect, boxes=0` 2. **第二次崩溃(02:05:05)**: - 运行时长:1140 秒(19 分钟) - 模式:Idle(完全空载,未启动检测) - 最后日志:`[HEARTBEAT] uptime=1140s mode=idle` **关键特征**: - ✅ 时间规律:精确的 20 分钟间隔 - ✅ 与业务逻辑无关:空载也崩溃 - ✅ 没有异常日志:所有 try-catch 未触发 - ✅ 业务流程完整:所有日志正常 **排除的原因**: - ❌ 不是 PNG 编码问题(已禁用) - ❌ 不是内存泄漏(htop 显示 < 1GB) - ❌ 不是检测算法问题(idle 也崩溃) - ❌ 不是异常退出(没有异常日志) - ❌ 不是 systemd 配置(服务文件没有超时设置) **可能的原因**: #### 1. 未捕获的信号(最可能) - 段错误(SIGSEGV) - 总线错误(SIGBUS) - 非法指令(SIGILL) - 其他致命信号 #### 2. 第三方库内部问题 - **MVS 相机 SDK** - 后台线程可能有 20 分钟的定时操作 - **ZeroMQ** - 内部定时器或清理任务 - **FFMedia (RTSP)** - 推流相关的定时任务 - **Qt 框架** - 事件循环或内部定时器 #### 3. 硬件或驱动问题 - USB 相机驱动在 20 分钟后触发某个问题 - GPIO 相关的驱动问题 - 系统资源限制 --- ## 🛠️ 最新解决方案 ### 方案 A:增加信号处理器(已实施)✅ **目的**:捕获导致崩溃的信号,打印调用栈 **修改文件**:`main.cpp` **新增功能**: 1. 注册信号处理器捕获: - SIGSEGV (段错误) - SIGABRT (异常终止) - SIGTERM (终止信号) - SIGINT (中断) - SIGILL (非法指令) - SIGFPE (浮点异常) - SIGBUS (总线错误) - SIGPIPE (管道破裂) 2. 崩溃时打印: - 信号类型和编号 - 完整的调用栈(backtrace) - 30 层函数调用 **预期效果**: - 如果是信号导致崩溃,会看到: ``` [SIGNAL] Caught signal X: SIGXXX (Description) [BACKTRACE] Stack trace (N frames): [0] function_name+0xoffset [1] function_name+0xoffset ... ``` --- ## 🧪 测试步骤 ### 1. 重新编译部署 ```bash cd GrabBagPrj qmake GrabBagPrj.pro make # 部署到设备 scp App/DroneScrewbolt/DroneScrewServer/DroneScrewServer user@device:/path/to/ ``` ### 2. 运行测试 ```bash # 重启服务 sudo systemctl restart dronescrewserver # 实时查看日志 sudo journalctl -u dronescrewserver.service -f ``` ### 3. 等待崩溃(约 20 分钟) 观察日志中是否出现: - `[SIGNAL] Caught signal X` - 说明捕获到信号 - `[BACKTRACE] Stack trace` - 崩溃时的调用栈 ### 4. 分析结果 #### 场景 A:看到信号日志 ``` [SIGNAL] Caught signal 11: SIGSEGV (Segmentation Fault) [BACKTRACE] Stack trace (15 frames): [0] signalHandler+0x123 [1] /lib/libc.so+0x456 [2] MV_CC_SomeFunction+0x789 ← 相机 SDK ... ``` → **根据调用栈定位问题** #### 场景 B:没有信号日志,直接退出 → **可能是 `_exit()` 或外部进程杀死** --- ## 📋 后续调试方案 ### 如果信号处理器捕获到了崩溃 根据调用栈分析: 1. **如果调用栈中有 `MV_CC_` 前缀** → MVS 相机 SDK 问题 2. **如果调用栈中有 `zmq_` 前缀** → ZeroMQ 问题 3. **如果调用栈中有 `ff_` 或 `av_` 前缀** → FFMedia/RTSP 问题 4. **如果调用栈中有我们的代码** → 代码逻辑问题 ### 如果信号处理器没有捕获到 说明不是信号导致,可能是: #### 1. 启用 coredump ```bash # 设置 coredump ulimit -c unlimited sudo mkdir -p /var/coredumps echo '/var/coredumps/core.%e.%p.%t' | sudo tee /proc/sys/kernel/core_pattern # 修改服务 sudo systemctl edit dronescrewserver.service # 添加: [Service] LimitCORE=infinity # 重启 sudo systemctl daemon-reload sudo systemctl restart dronescrewserver # 崩溃后分析 gdb /path/to/DroneScrewServer /var/coredumps/core.xxx.xxx.xxx (gdb) bt (gdb) thread apply all bt ``` #### 2. 使用 strace 跟踪系统调用 ```bash sudo strace -f -tt -T -o /tmp/strace.log /path/to/DroneScrewServer ``` #### 3. 使用 valgrind 检查内存问题 ```bash valgrind --leak-check=full --track-origins=yes /path/to/DroneScrewServer ``` #### 4. 临时禁用相机回调测试 如果怀疑是 MVS SDK 问题,可以临时注释掉相机初始化,看是否还崩溃: ```cpp // presenter.initAll(); // 临时注释 ``` #### 5. 禁用 RTSP 推流测试 ```cpp // m_pPusher = ...; // 临时设置为 nullptr ``` --- ## 📊 修改文件清单 ### 已修改的文件 | 文件 | 修改内容 | 状态 | |------|---------|------| | `DroneScrewZmqProtocol.cpp` | 禁用 PNG 压缩 | ✅ 完成 | | `DroneScrewServerPresenter.cpp` | 增加检测流程详细日志 | ✅ 完成 | | `main.cpp` | 增加信号处理器和调用栈打印 | ✅ 完成 | ### 文档 | 文档 | 说明 | |------|------| | `CRASH_FIX_SUMMARY.md` | 第一轮异常保护总结 | | `DIAGNOSTIC_LOG_ENHANCEMENT.md` | 诊断日志增强说明 | | `CRASH_ROOT_CAUSE_ANALYSIS.md` | PNG 崩溃根因分析 | | `CRASH_20MIN_TIMEOUT_ANALYSIS.md` | 20 分钟崩溃分析 | | `CRASH_FINAL_SOLUTION.md` | **完整解决方案(本文档)** | --- ## 🎯 预期结果 ### 运行新版本后 **如果是信号导致崩溃**: - 日志中会出现 `[SIGNAL] Caught signal X` - 会有完整的调用栈 - 可以立即定位问题 **如果不是信号导致**: - 继续按照后续调试方案进行 - 使用 coredump 或 strace 深入分析 --- ## 📞 下一步 **请执行以下操作**: 1. ✅ **重新编译部署**新版本(包含信号处理器) 2. ✅ **运行至少 30 分钟**,等待崩溃 3. ✅ **提供完整日志**,特别是崩溃前后的日志 4. ✅ **查找 `[SIGNAL]` 关键字**,看是否捕获到信号 **关键日志命令**: ```bash # 查看最近 2 小时的日志 sudo journalctl -u dronescrewserver.service --since "2 hours ago" > /tmp/crash.log # 查找信号相关日志 grep -A 50 "\[SIGNAL\]" /tmp/crash.log # 查找崩溃相关日志 grep -B 30 -A 10 "Main process exited" /tmp/crash.log ``` --- ## 💪 我们会找到根本原因的! 通过信号处理器和详细的调用栈,我们应该能够精确定位问题所在。请尽快测试并提供新的日志!