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

260 lines
6.7 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 崩溃根因最终分析
## 🎯 最新发现2026-06-04
### 崩溃模式确认
经过多次测试和日志分析,发现了以下关键信息:
#### 测试 1PNG 编码崩溃(已解决)
- **崩溃点**`[PUB-raw] before PNG encode`
- **原因**PNG 编码库段错误
- **解决方案**:禁用 PNG 压缩
- **状态**:✅ 已修复
#### 测试 2禁用 PNG 后仍崩溃(新问题)
**第一次崩溃01:44:59**
```
运行时长:约 20 分钟
模式:检测模式
最后日志:[DETECT] frame #2041 after algo Detect, boxes=0
退出码255
```
**第二次崩溃02:05:05**
```
运行时长:约 20 分钟1140秒
模式Idle完全空载
最后日志:[HEARTBEAT] uptime=1140s mode=idle
退出码255
```
### 🔍 关键线索
1. **时间规律性**
- 两次崩溃都在启动后约 **19-20 分钟**
- 与是否运行检测**无关**
- 与处理的帧数**无关**
2. **Idle 模式也崩溃**
- 程序完全空载(没有检测、没有图像处理)
- 仅运行心跳日志
- 说明**不是业务逻辑代码的问题**
3. **没有异常日志**
- 所有 try-catch 都没有捕获到异常
- 所有业务流程日志都完整
- 崩溃发生在**代码逻辑之外**
## 💡 根本原因推断
### 最可能的原因systemd 看门狗或超时配置
#### 证据:
1. **精确的 20 分钟间隔**:不像随机崩溃,更像超时强制终止
2. **退出码 255**:异常退出,但非段错误(段错误通常是 139
3. **systemd 日志**`Main process exited, code=exited, status=255/EXCEPTION`
4. **Idle 也崩溃**:排除了所有业务代码问题
#### systemd 可能的配置:
```ini
[Service]
RuntimeMaxSec=20m # 运行时间上限 20 分钟
# 或
WatchdogSec=20m # 看门狗超时 20 分钟
# 或
TimeoutStopSec=20m # 停止超时
```
### 其他可能性(概率较低)
#### 1. Qt 事件循环死锁
- Qt 主事件循环卡死
- 某个线程持有锁不释放
- 但这通常不会有精确的 20 分钟间隔
#### 2. 内存泄漏导致 OOM-Killer
- 但 htop 显示内存 < 1GB
- 而且 OOM-Killer 的退出码通常是 9 (SIGKILL)
#### 3. 相机 SDK 内部问题
- MVS SDK 的后台线程崩溃
- 但为什么会是精确的 20 分钟
## 🛠️ 解决方案
### 方案 1检查 systemd 服务配置(优先)
**步骤**
```bash
# 查看当前服务配置
sudo systemctl cat dronescrewserver.service
# 查看完整状态
sudo systemctl status dronescrewserver.service
# 查看服务属性
sudo systemctl show dronescrewserver.service | grep -i "timeout\|watchdog\|runtime"
```
**如果发现超时配置,修改服务文件**
```ini
[Service]
# 移除或增加运行时间限制
# RuntimeMaxSec=infinity # 或设置更长时间
# WatchdogSec=0 # 禁用看门狗
# 增加停止超时(避免强制杀死)
TimeoutStopSec=30s
# 重启策略
Restart=always
RestartSec=5s
```
**应用配置**
```bash
sudo systemctl daemon-reload
sudo systemctl restart dronescrewserver
```
### 方案 2启用 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
# 修改 systemd 服务
sudo systemctl edit dronescrewserver.service
# 添加:
[Service]
LimitCORE=infinity
# 重启
sudo systemctl daemon-reload
sudo systemctl restart dronescrewserver
# 崩溃后查看 coredump
ls -lh /var/coredumps/
# 使用 gdb 分析
gdb /path/to/DroneScrewServer /var/coredumps/core.xxx
```
### 方案 3增加详细的系统调用跟踪
```bash
# 使用 strace 跟踪(会影响性能)
sudo systemctl stop dronescrewserver
sudo strace -f -o /tmp/dronescrew_strace.log /path/to/DroneScrewServer
# 或修改 systemd 服务
[Service]
ExecStart=/usr/bin/strace -f -o /tmp/dronescrew_strace.log /path/to/DroneScrewServer
```
### 方案 4修改代码增加信号处理器
`main.cpp` 中增加信号处理捕获崩溃信号
```cpp
#include <signal.h>
#include <execinfo.h>
void signalHandler(int sig)
{
void* array[20];
size_t size = backtrace(array, 20);
LOG_ERROR("========== SIGNAL %d RECEIVED ==========\n", sig);
LOG_ERROR("Stack trace:\n");
char** messages = backtrace_symbols(array, size);
for (size_t i = 0; i < size; i++)
LOG_ERROR(" [%zu] %s\n", i, messages[i]);
free(messages);
exit(sig);
}
int main(int argc, char* argv[])
{
// 注册信号处理器
signal(SIGSEGV, signalHandler); // 段错误
signal(SIGABRT, signalHandler); // 异常终止
signal(SIGTERM, signalHandler); // 终止信号
signal(SIGKILL, signalHandler); // 强制终止(无法捕获,但尝试)
// ... 原有代码 ...
}
```
## 📊 优先级和推荐
### 立即执行(优先级 P0
1. **检查 systemd 服务配置**
```bash
sudo systemctl show dronescrewserver.service | grep -i "timeout\|watchdog\|runtime"
```
2. **查看完整的 systemd 日志**
```bash
sudo journalctl -u dronescrewserver.service --since "1 hour ago" | grep -i "timeout\|killed\|signal"
```
### 短期(优先级 P1
3. **启用 coredump**(如果是段错误)
4. **增加信号处理器**(捕获终止信号)
### 中期(优先级 P2
5. **代码审查**
- 检查是否有死锁可能
- 检查线程退出逻辑
- 检查资源清理
## 🧪 测试验证
### 验证步骤
1. **查看 systemd 配置**后,运行测试:
- 如果有 20 分钟限制 → 移除后测试能否运行超过 20 分钟
- 如果没有限制 → 继续其他方案
2. **启用 coredump** 后,等待下次崩溃:
- 查看是否生成了 coredump 文件
- 使用 gdb 分析崩溃点
3. **增加信号处理器** 后,查看日志:
- 如果看到 "SIGNAL XX RECEIVED",说明是信号导致
- 根据信号类型判断原因
## 📈 下一步行动
**请先执行以下命令并提供输出**
```bash
# 1. 查看 systemd 服务完整配置
sudo systemctl cat dronescrewserver.service
# 2. 查看服务超时相关属性
sudo systemctl show dronescrewserver.service | grep -E "RuntimeMaxSec|WatchdogSec|TimeoutStopSec|TimeoutStartSec"
# 3. 查看最近的 systemd 日志(包含信号信息)
sudo journalctl -u dronescrewserver.service --since "2 hours ago" | tail -100
```
根据这些信息我们就能确定是否是 systemd 配置问题然后针对性解决
## 📝 修改记录
| 日期 | 问题 | 解决方案 | 状态 |
|------|------|---------|------|
| 2026-06-04 | PNG 编码崩溃 | 禁用 PNG 压缩 | 已修复 |
| 2026-06-04 | 20 分钟定时崩溃 | 待确认 systemd 配置 | 🔍 调查中 |