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

183 lines
5.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 崩溃问题修复总结
## 问题描述
程序在运行约 20 分钟后崩溃(退出码 255日志显示
- 处理了约 2100 帧图像后突然退出
- 没有任何错误日志,表明发生了未捕获的异常或段错误
- 最后日志:`right frame #2100` → 直接崩溃
## 根本原因分析
从代码审查发现以下风险点:
### 1. **相机回调函数缺少异常保护**(最可能的原因)
- `leftCameraCallback``rightCameraCallback` 在相机 SDK 线程中被调用
- 包含内存分配、拷贝、RTSP 推流等操作,但没有 try-catch
- 任何异常都会导致程序崩溃
### 2. **心跳日志内存信息不完整**
- `procStatusValue("VmRSS")` 返回空字符串
- 无法监控内存增长情况
### 3. **算法库调用缺少保护**
- `m_pAlgo->Detect()` 可能抛出异常
- 第三方算法库崩溃会导致整个进程退出
### 4. **GPIO 触发线程缺少异常保护**
- 长时间运行的线程没有顶层异常捕获
## 修复方案
### 1. 相机回调异常保护(关键修复)
**文件**: `DroneScrewServerPresenter.cpp`
#### `leftCameraCallback` 函数
- 整个函数体包裹在 `try-catch`
- 捕获 `std::bad_alloc``std::exception` 和未知异常
- 增加内存重新分配的日志realloc log
```cpp
void DroneScrewServerPresenter::leftCameraCallback(const MvsImageData& img)
{
try
{
// ... 原有逻辑 ...
}
catch (const std::bad_alloc& e)
{
LOG_ERROR("[CAM] left callback bad_alloc frame=%llu size=%zu: %s\n", ...);
}
catch (const std::exception& e)
{
LOG_ERROR("[CAM] left callback exception frame=%llu: %s\n", ...);
}
catch (...)
{
LOG_ERROR("[CAM] left callback unknown exception frame=%llu\n", ...);
}
}
```
#### `rightCameraCallback` 函数
- 同样增加异常保护
- 增加内存重新分配的日志
### 2. 算法调用异常保护
**文件**: `DroneScrewServerPresenter.cpp``detectThreadFunc()`
```cpp
if (m_pAlgo)
{
try
{
m_pAlgo->Detect(inLeft, inRight, result);
}
catch (const std::exception& e)
{
LOG_ERROR("[DETECT] algo exception frame=%llu: %s\n", ...);
result.success = false;
result.errorCode = -1;
result.message = std::string("Algorithm exception: ") + e.what();
}
catch (...)
{
LOG_ERROR("[DETECT] algo unknown exception frame=%llu\n", ...);
// ... 设置错误状态 ...
}
}
```
### 3. GPIO 触发线程异常保护
**文件**: `DroneScrewServerPresenter.cpp``triggerThreadFunc()`
- 整个 while 循环包裹在 try-catch 中
- 防止 GPIO 操作异常导致程序崩溃
### 4. 增强心跳日志
**文件**: `main.cpp`
```cpp
const QString rss = procStatusValue("VmRSS");
const QString vmPeak = procStatusValue("VmPeak");
const QString vmSize = procStatusValue("VmSize");
const QString threads = procStatusValue("Threads");
LOG_INFO("[HEARTBEAT] uptime=%llds mode=%s rss=%s vmPeak=%s vmSize=%s threads=%s\n",
...,
rss.isEmpty() ? "N/A" : rss.toStdString().c_str(),
...);
```
增加的字段:
- `vmPeak`: 峰值虚拟内存
- `vmSize`: 当前虚拟内存
- 空值显示为 "N/A" 而非空字符串
## 诊断日志增强
### 相机回调
- 内存重新分配时打印旧/新 size
- 异常时记录帧 ID、数据大小和异常信息
### 心跳监控
- 显示内存使用趋势RSS、VmPeak、VmSize
- 线程数量监控
### 算法调用
- 异常时记录帧 ID 和错误信息
- 将错误信息传递给结果对象
## 测试建议
1. **长时运行测试**
- 运行 30 分钟以上,观察是否还会崩溃
- 监控心跳日志中的内存变化
2. **关键日志观察**
```bash
# 监控异常日志
grep -E "exception|unknown exception|bad_alloc" log.log
# 监控内存增长
grep "HEARTBEAT" log.log
# 监控内存重新分配
grep "realloc" log.log
```
3. **预期结果**
- 如果是相机回调异常:会看到 `[CAM] left/right callback exception` 但程序不崩溃
- 如果是算法异常:会看到 `[DETECT] algo exception` 但程序继续运行
- 如果是内存泄漏:心跳日志会显示内存持续增长
- 如果是 GPIO 异常:会看到 `[GPIO] trigger thread exception` 但程序不崩溃
## 下一步行动
1. **编译并部署**修改后的代码
2. **运行至少 30 分钟**,观察日志
3. **记录所有异常日志**,分析根本原因
4. **根据日志反馈**进行针对性修复
## 注意事项
- 所有异常捕获都会记录日志,不会静默失败
- 异常保护只是防止崩溃,并不解决根本问题
- 看到异常日志后需要进一步分析根本原因
- 如果频繁出现异常,说明存在更深层的问题需要修复
## 修改文件清单
1. `App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.cpp`
- `leftCameraCallback()` - 增加异常保护和内存重分配日志
- `rightCameraCallback()` - 增加异常保护和内存重分配日志
- `detectThreadFunc()` - 算法调用增加异常保护
- `triggerThreadFunc()` - 增加异常保护
2. `App/DroneScrewbolt/DroneScrewServer/main.cpp`
- 心跳日志增强:增加 vmPeak、vmSize 字段
- 处理空值显示为 "N/A"