GrabBag/App/DroneScrewbolt/CRASH_FINAL_SOLUTION.md

290 lines
7.2 KiB
Markdown
Raw Normal View History

2026-06-26 17:55:15 +08:00
# 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
```
---
## 💪 我们会找到根本原因的!
通过信号处理器和详细的调用栈,我们应该能够精确定位问题所在。请尽快测试并提供新的日志!