# 2026-09-15 连续生成近 6 小时后整机硬挂（掉线）—— 现场取证报告

> 结论（09-15 20:xx 二次修订）：**不是 SageAttention 复发、不是供电瞬断、也不是单纯过热——最可能是
> 生成时宿主内存被吃干 + ComfyUI 允许 pin 住 27.1 GiB 不可换页内存所导致的内存回收/驱动路径卡死。**
> 依据：① 掉线期间**屏幕仍显示画面、光标静止不闪、键盘无反应** → 供电正常，是整机内核冻结；
> ② 同样满载数小时的 **LLM 从不掉线，只有 ComfyUI 生成 H3 才冻死** → 热量/电源/时长不是主因；
> ③ 生成中实测 ComfyUI **RSS 28.3 GiB / 31.1 GiB**、`MemAvailable` 仅 1.64 GB、8 GB 交换文件 100% 满、
> `vmstat` 出现 si=1479/so=2234 的换页抖动，而 ComfyUI 的 pinned 上限按公式算正好是 **27.1 GiB**。
> journald 在 18:38:35 CST 直接断掉，无 Xid / NVRM / 温度 / MCE / hung task / panic 任何一条，
> 整机网络（ARP/ICMP/SSH）同时消失，一直死到 22 分 42 秒后**人工按电源复位**——因为这台机器被配置成
> 「死机就永久死着」（`panic=0`、`hung_task_panic=0`、`softlockup_panic=0`、`hardlockup_panic=0`、
> 无 pstore、无 kdump），所以没留下死因。

## 一、时间线（CST = 北京时间；括号内为 UTC）

| 时间 | 事件 | 来源 |
|---|---|---|
| 09-14 22:37:17 | 上一个 boot 启动（本次连续生成会话所在的那次开机） | `journalctl --list-boots` boot -1 |
| 09-15 18:10:49 | **最后一个成功产出**：`MiniMaxH3_Director_rv2v_00020_.mp4` 入库相册 | gallery-sync.log `10:10:49 新收录` |
| 09-15 18:37 前后 | ComfyUI 正在跑一个 **2 段 × 200 帧（共 400 帧 @24fps）的 rv2v、10 步**任务，已到 **segment 2/2 的 7/10 步**（≈54.5 秒/步）；segment 1/2 已完成（200 帧） | ComfyUI 日志末行 `70%\|\|███\| 7/10 [07:16<02:43, 54.45s/it]`，文件 mtime 10:37 |
| 09-15 18:38:35 | **机器最后一条日志**：一次来自 192.168.31.114（DSH 机）的 SSH 会话打开（gallery rsync 周期），此后 journald 再无任何记录 | `journalctl -b -1 --since 10:37:00` 末行 |
| 09-15 18:39:35 | gallery sync 首个失败：`rsync exit 30 io timeout after 30 seconds` → 随即 `Connection timed out` → `No route to host` | gallery-sync.log |
| 09-15 19:01:22 | 新 boot 启动（boot 0 `f40d43c2…`）→ **从挂死到恢复共 22 分 42 秒** | `journalctl --list-boots` |
| 09-15 19:01+ | 复检：GPU 正常（RTX 5060 Ti / 610.43.02 / 0% / 18 MiB / 38 °C / 8.8 W），**ComfyUI 进程不在**（本机设计为不自启） | `nvidia-smi` / `ps` |

## 二、硬证据

1. **日志断得很干脆**：boot -1 的最后一条是 10:38:35 的 SSH 会话打开，**没有**任何关机流程
   （对比 09-14 04:57 那次有明确的 `shutdown system down` 记录）。
2. **内核零报错**：`journalctl -b -1 -k | grep -iE "xid|nvrm|nvidia|gsp|thermal|throttl|mce|edac|hung task|blocked for more|Oops|BUG:|panic|watchdog|pcie.*(error|down)"`
   → 除开机时的常规 PCIe/EDAC/NVRM 加载信息外，**零命中**。
3. **ComfyUI 是被整体带走的**：日志停在采样第 7/10 步，之后连一行 VAE 解码、报错、中断都没有。
4. **网络同时消失**：18:39:35 起 rsync 先 30 秒 I/O 超时、再 `No route to host`，说明不是「ComfyUI 崩了但机器还在」。
5. **SageAttention 不在场**（关键排除项）：整份 ComfyUI 日志 `grep -i sage` 命中 7 处，全是
   `message` / `Usage` 这类假匹配 → 本次运行**没有** `PathchSageAttentionKJ` /
   `MiniMaxH3MemoryEfficientSageAttentionPatch` 之类节点。09-14 的元凶与本次无关，那次的修复是有效的。
6. **没有任何自动恢复机制**：`RuntimeWatchdogSec=off`（systemd 默认注释）、`/dev/watchdog` 不存在
   （没加载硬件看门狗驱动）、`nmi_watchdog=1`（只打印 hardlockup，不会重启）。
7. **崩溃前日志会丢**：`/var/log/journal` 存在（持久化 ✓），但 journald 默认
   `SyncIntervalSec=5m` → 崩溃前最多 5 分钟的数据可能还在页面缓存里没落盘（这次丢掉的正是最后约 1 分钟）。

## 三、成因判断（诚实版：无法只凭现有日志定论）

「无任何内核报错 + 日志瞬断 + 整机网络同时消失」这个组合，符合以下三类之一：

| 假设 | 支持点 | 反对/待验证 |
|---|---|---|
**用户现场观察（决定性证据，09-15 19:2x 补充）：掉线期间屏幕仍在显示画面，但光标静止不闪烁、
键盘输入无任何反应。**

| 假设 | 支持点 | 结论 |
|---|---|---|
| **A. 供电瞬断 / PSU 保护动作** | 日志瞬断、无任何报错 | ❌ **基本排除**：真断电会让显示器失去信号（黑屏 / No Signal）；而画面还亮着、只是冻住 |
| **B. 整机级内核冻结（CPU / GPU 驱动锁死）** | 屏幕继续扫描出最后一帧（显示控制器与内核 VT 仍在输出）但光标不闪、输入无响应、不回 ARP/ICMP、22 分钟不自愈——**这是内核已停止调度的典型表现** | ✅ **当前主因**。缺的是「为什么锁死」：可能是 NVIDIA 驱动（NVRM/GSP）阻塞把整机拖进 D 状态，或 CPU 硬锁死 |
| **C. 硬件复位（VRM / 主板 / 内存）** | 无 | 降权：本质仍是断电重启，同样解释不了「屏幕还亮着」 |

**结论：供电未断，是整机内核冻结。** 之所以拿不到原因，是因为这台机器**根本没有崩溃捕获能力**：

| 机制 | 现状 | 后果 |
|---|---|---|
| `kernel.panic` | **0** | 崩溃后不自动重启 |
| `kernel.panic_on_oops` | **0** | oops 不升级为 panic |
| `kernel.hung_task_panic` | **0**（timeout 120s） | 进程卡 D 状态 120 秒也不 panic |
| `kernel.softlockup_panic` / `hardlockup_panic` | **0 / 0** | 软/硬锁死只打印不重启（`nmi_watchdog=1` 只在还能写盘时有用） |
| `/sys/fs/pstore` | **空** | 固件不上报崩溃残留 |
| `kdump-tools` | **未安装**（`not-found`） | 没有 vmcore |
| journald | 持久化 ✓，但 `SyncIntervalSec=5m` | 崩溃前最多 5 分钟日志可能丢（这次丢了最后约 1 分钟） |

另外两种可能已被排除：
- **不是软件主动重启**：boot -1 无 shutdown 序列，`last -x` 也没有对应的 shutdown 记录；
- **不是 SageAttention 复发**：见证据 5。

### 三·补（09-15 20:xx 新增，**最强线索**）：生成时宿主内存被吃干 + ComfyUI 可锁定 27 GB 不可换页内存

用户补充的关键对照事实：**跑 LLM（LM Studio / ridge，llama.cpp）时同样连续满载数小时，从不掉线；
只有 ComfyUI 生成 H3 才会冻死。** 这就把「热量 / 电源 / 时长」基本排除——同样是 100% 满载、同样 81 ℃、
同样 145 W，LLM 不出事。差别在**宿主内存与驱动路径**：

生成中实测（同一时刻采样）：

| 指标 | 实测值 | 说明 |
|---|---|---|
| ComfyUI 进程 RSS (`VmRSS`) | **28,999,508 kB ≈ 28.3 GiB** | 占 31.1 GiB 物理内存的 **91%**；第二名 dockerd 只有 35 MB |
| ComfyUI 被换出的内存 (`VmSwap`) | **5.37 GiB** | 连它自己的页都被换到磁盘 |
| `MemFree` / `MemAvailable` | **372 MB / 1.64 GB** | 剩余可用内存几乎为零 |
| Swap 使用 | **8.4 GB**（`/swap.img` 8 GB **100% 满**） | 第二个 64 GB 的 `/swap2.img` 才用了 196 MB |
| `vmstat` 换页 | 一次采样 **si=1479 / so=2234 页/秒**；`SwapCached` **2.4 GB** | 典型的**换页抖动（thrash）**，页面被反复换出又换回 |
| OOM kill / 分配失败 | **0 次** | 内核没杀进程，而是靠抖动硬扛 → 更容易演变成长时间卡死 |

而 `--lowvram` 模式下 ComfyUI 自己算出来的「可锁定内存上限」更是雪上加霜（源码 `comfy/model_management.py:1585-1593`）：

```python
MAX_PINNED_MEMORY = max(ram*0.40, min(ram*0.90, ram - 4*GiB, ram + swap - 16*GiB))
```

本机 ram=31.1 GiB、swap=72 GiB 代入：`max(12.5, min(28.0, 27.1, 87.1)) = 27.1 GiB`
→ 日志里那句 `Enabled pinned memory 27792` 就是它：**ComfyUI 允许自己 pin 住 27.1 GiB 的
「不可换页」宿主内存**，而机器只有 31.1 GiB。pinned 内存无法被换出，一旦内存已经吃紧、
内核再去 reclaim，就极易在内存回收 / 驱动内存管理路径上长时间停住——这与「屏幕还亮着、
光标不动、输入无反应、无任何内核报错、22 分钟不自愈」的表现一致。

**为什么 LLM 没事**：llama.cpp / LM Studio 是把 GGUF **mmap** 进来、KV cache 一次分配，
RSS 有界（十几 GB），没有 cudaMalloc 抖动，也没有「按 RAM 比例算出来的 pinned 池」；
所以同样满载数小时不触发内存回收风暴。

⚠️ **诚实边界**：以上是「运行在内存抖动区间」的**机制性证据**，不等于已经证明死锁发生在
reclaim 路径里——要坐实仍需 netconsole / panic 捕获（本报告 P0 那套，你目前选择不装）。

可用的现成开关（都在 ComfyUI 自己的参数里，无需改代码）：
- `--disable-pinned-memory`（`cli_args.py:202`，官方说明 "Disable pinned memory use."）→ 直接去掉那 27 GB 的不可换页池；
- `--cache-lru 20`（`cli_args.py:142`，官方说明 "**May use more RAM/VRAM**"）→ 降到 2 或去掉；
- `--fast-disk`（`cli_args.py:182`，"Prefer disk-backed dynamic loading and offload **over unpinned RAM**"）→ 保留，方向正确；
- 根治：内存加到 64 GB。

## 四、损失

- 那个 **2 段×200 帧 / 10 步的 rv2v 任务**：segment 1/2 已完成（200 帧），
  segment 2/2 卡在 7/10，**最终合并从未发生** → 没有成品文件，需要整条重跑。
- 最后一个成功产出是 **00020**（18:10 CST，已在相册 http://192.168.31.76:8900 ）。
- 22 分 42 秒的整机不可用 + 需要人工重启 ComfyUI。

## 五、建议（按优先级）

### ★ 最优先（本次新证据）：先把宿主内存窒息解除

比装任何监控都直接——把这次冻死的**土壤**去掉（32 GB 内存跑 20 GB 模型 + 5 GB VAE 的 `--lowvram` 本就吃紧）：

1. **去掉 pinned 池**：启动参数加 `--disable-pinned-memory`（当前它允许 pin 27.1 GiB 不可换页内存）；
2. **砍缓存**：`--cache-lru 20` → `--cache-lru 2` 或直接去掉（官方原话 "May use more RAM/VRAM"）；
3. **保留** `--fast-disk`（它明确偏向磁盘后备、少占非 pinned RAM，方向是对的）；
4. **生成期间盯一个数**（不用装东西）：
   ```bash
   while :; do grep -E "MemAvailable|SwapFree" /proc/meminfo | tr '\n' ' '; echo; sleep 30; done
   ```
   `MemAvailable` 掉到 1 GB 以下、或 `SwapFree` 持续下降 → 已经进入危险区；
5. **根治**：内存 32 GB → 64 GB（H3 + 多段长视频在 32 GB 上已无余量）。

### P0：让它「死了也留下证据」——netconsole（零重启风险，模块已确认存在）

`modinfo netconsole` → `/lib/modules/6.8.0-139-generic/kernel/drivers/net/netconsole.ko.zst` ✓

把内核 printk 通过 UDP 实时发到 DSH 机（192.168.31.76）。**整机冻死时磁盘写不进去，但网卡的
printk 路径仍可能把最后几条带出去**——这是「屏幕冻住」这类故障唯一可靠的取证手段。
配套：DSH 侧跑一个 UDP 接收器落盘（`~/netconsole-recv.py` + systemd 单元，日志 `netconsole-<host>.log`）。

### P1：把它从「永久冻结」改成「崩溃 + 自动重启」

| 参数 | 建议值 | 作用 |
|---|---|---|
| `kernel.hardlockup_panic` | 1 | CPU 硬锁死 → panic（`nmi_watchdog` 已在跑） |
| `kernel.softlockup_panic` | 1 | CPU 软锁死 → panic |
| `kernel.hung_task_panic` | 1（`hung_task_timeout_secs` 提到 300） | 进程卡 D 状态 → panic（300s 避免慢 I/O 误触发） |
| `kernel.panic` | 10 | panic 后 10 秒自动重启 |

效果：**这次那种「死着等人来按电源」22 分钟 → 约 2 分钟内自动重启**，且 panic 内容会被 netconsole 带走。

### P2：让日志活到最后一刻

journald `SyncIntervalSec=5s`（默认 5m → 5s，代价是更频繁的小写入）。

### P3（可选，较重）：kdump 抓 vmcore

需要 `crashkernel=` 预留内存 + 安装 `kdump-tools` + 重启，能拿到完整内存转储；
代价是牺牲一部分内存、配置更复杂。要彻底定位「哪个驱动锁死」时再上。

### P4：降低单次损失

- 长任务分段提交（这次是 2 段×200 帧，卡在第 2 段就全丢；小段可只丢最后一段）；
- ComfyUI 重启已是一条命令（`~/restart_comfy.sh` 已有）。

### ⚠️ 更正：用户态记录器对这种「整机冻死」无效

先前建议的 `gpu-forensic-logger.sh` 是**用户态**进程——内核已经停止调度时它根本不会被执行，
所以**抓不到这次的故障**（它适合温度/功耗趋势、部分降级、GPU 单点异常这类「系统还活着」的场景）。
针对这次这种屏幕冻住的整机锁死，正确的工具是**内核态路径：netconsole + panic-on-lockup**。

## 六、本次产出的脚本

| 文件 | 用途 | 部署位置 |
|---|---|---|
| `scripts/gpu-forensic-logger.sh` | 崩溃前取证记录器（20s 一次，含 fsync） | GPU 机 `~/gpu-forensic-logger.sh` |
| `scripts/gpu-forensic-logger.service` | 上述记录器的 systemd 单元（Restart=always，CPUQuota=10%） | GPU 机 `/etc/systemd/system/` |
| `scripts/comfyui-stall-watchdog.sh` | 生成中途卡死检测（默认只记录，`REBOOT_ON_STALL=1` 才重启） | GPU 机 `~/comfyui-stall-watchdog.sh` |

日志位置：`~/gpu-forensic.log`（200MB 轮转）、`~/comfyui-stall.log`。
