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

6.7 KiB
Raw Blame History

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 可能的配置:

[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 服务配置(优先)

步骤

# 查看当前服务配置
sudo systemctl cat dronescrewserver.service

# 查看完整状态
sudo systemctl status dronescrewserver.service

# 查看服务属性
sudo systemctl show dronescrewserver.service | grep -i "timeout\|watchdog\|runtime"

如果发现超时配置,修改服务文件

[Service]
# 移除或增加运行时间限制
# RuntimeMaxSec=infinity  # 或设置更长时间
# WatchdogSec=0          # 禁用看门狗

# 增加停止超时(避免强制杀死)
TimeoutStopSec=30s

# 重启策略
Restart=always
RestartSec=5s

应用配置

sudo systemctl daemon-reload
sudo systemctl restart dronescrewserver

方案 2启用 coredump 定位段错误(如果是段错误)

# 启用 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增加详细的系统调用跟踪

# 使用 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 中增加信号处理,捕获崩溃信号:

#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 服务配置

    sudo systemctl show dronescrewserver.service | grep -i "timeout\|watchdog\|runtime"
    
  2. 查看完整的 systemd 日志

    sudo journalctl -u dronescrewserver.service --since "1 hour ago" | grep -i "timeout\|killed\|signal"
    

短期(优先级 P1

  1. 启用 coredump(如果是段错误)
  2. 增加信号处理器(捕获终止信号)

中期(优先级 P2

  1. 代码审查
    • 检查是否有死锁可能
    • 检查线程退出逻辑
    • 检查资源清理

🧪 测试验证

验证步骤

  1. 查看 systemd 配置后,运行测试:

    • 如果有 20 分钟限制 → 移除后测试能否运行超过 20 分钟
    • 如果没有限制 → 继续其他方案
  2. 启用 coredump 后,等待下次崩溃:

    • 查看是否生成了 coredump 文件
    • 使用 gdb 分析崩溃点
  3. 增加信号处理器 后,查看日志:

    • 如果看到 "SIGNAL XX RECEIVED",说明是信号导致
    • 根据信号类型判断原因

📈 下一步行动

请先执行以下命令并提供输出

# 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 配置 🔍 调查中