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

290 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DroneScrewServer 崩溃问题完整解决方案
## 📊 问题总结
### 问题 1PNG 编码崩溃 ✅ 已解决
**现象**
- 程序在检测模式下运行约 19 分钟后崩溃
- 崩溃发生在 PNG 编码过程中
- 日志显示:`[PUB-raw] before PNG encode` → 崩溃
**根本原因**
- PNG 编码库在 ARM 平台处理 4096x3000 大图像时发生段错误
- OpenCV 或 libpng 的内部问题
**解决方案**
- 禁用 PNG 压缩,使用原始格式传输
- 文件:`DroneScrewZmqProtocol.cpp`
- 修改:强制 `usePng = false`
**影响**
- ✅ PNG 崩溃已完全解决
- ⚠️ 网络带宽从 ~10MB/帧 增加到 ~24MB/帧
- ✅ 千兆局域网完全足够(占用 38% 带宽)
---
### 问题 220 分钟定时崩溃 🔍 调查中
**现象**
- 禁用 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
```
---
## 💪 我们会找到根本原因的!
通过信号处理器和详细的调用栈我们应该能够精确定位问题所在请尽快测试并提供新的日志