Skip to content

[Bug] 代码走查:PLY 头解析失败、失败时进度条显示 100%、日志封顶后停止滚动等 5 处缺陷 #13

Description

@leason12138-code
## 概述`0.2.0` 做了一轮静态走查,发现 5 处值得修复的缺陷,按影响排序。全部可在本地复现或由代码逻辑直接推出。

---

### 1. PLY 头解析脆弱,可能在训练完成后误判产物无效(最高优先级)

`src-tauri/src/reconstruction/ply.rs:18-21`

```rust
let mut bytes = vec![0_u8; (size.min(256 * 1024)) as usize];
let read = file.read(&mut bytes)?;
  • Read::read 允许短读,返回少于 256KB 也合法。此时 end_header 可能落在未读区域,报错「PLY 缺少 end_header」。失败点在 Brush 训练完成之后,用户损失最大。
  • ply.rs:37-49 属性校验用 line.ends_with(" x"),但 header.lines() 会保留 CRLF 的 \r,CRLF 头必然匹配失败,报「PLY 缺少 Gaussian 属性」。而同函数 :26 又显式接受 ply\r\n,逻辑自相矛盾。

建议:改用 file.take(n).read_to_end(&mut bytes);所有头行统一 trim_end() 后再比较。


2. 失败/取消时进度条跳到 100%,时间线全部标绿

  • src-tauri/src/pipeline/progress.rs:16Failed | Cancelled => (0.0, 100.0)
  • src-tauri/src/commands/mod.rs:115PipelineEvent::mapped(stage, 1.0, error.to_string())progress = 100
  • src/stores/appStore.ts:65Math.max(...) 把进度锁死在 100%
  • src/app/App.tsx:47failed/cancelled 映射到 stage index 6,:295 据此把前 6 个阶段渲染为 done

结果:任务在「顺序匹配」失败,UI 却显示 100.0% 且所有阶段已完成。

建议:终止事件不参与进度更新(前端过滤,或后端携带终止前的真实进度);时间线的 done 判定改用终止前记录的阶段索引。


3. 日志超过 500 条后停止自动滚动

src/app/App.tsx:141

useEffect(() => { logEnd.current?.scrollIntoView({ block: "nearest" }); }, [store.events.length]);

appStore.ts:61 对日志做了 slice(-500) 封顶,长度恒为 500 后依赖值不再变化,effect 不再触发。长任务(精细档位 Brush 训练)后期日志不跟随底部。

建议:依赖改为 store.events(每次 receiveEvent 都是新数组,引用必变)。


4. 完成结果与注册率警告从未展示给用户

  • App.tsxstore.result 只写不读,完成后的 splat 数量、PLY 大小、路径、耗时均不渲染。
  • runner.rs:472 生成的 PipelineResult.warning(注册率 50%–80% 的质量警告)被完全丢弃,与 README「50%–80% 时给出质量警告并继续」不符。
  • src/lib/backend.ts:46exportPly 无任何调用点,是死代码。

建议phase === "completed" 时渲染结果卡片,含 warning 提示条,并接上「导出 PLY / 在文件管理器中显示」。


5. 失败或取消时 state.json 丢失全部进度

src-tauri/src/pipeline/runner.rs:335-341

let mut state = PipelineStateFile::created(quality);
state.stage = if cancelled { Cancelled } else { Failed };

run_project 内部维护的 statevideo / frames / features_complete / matching_complete / reconstruction_complete)是局部变量,错误路径拿不到,于是用一个空白 state 覆盖磁盘,事后诊断信息全部丢失。

建议:错误分支先读回磁盘上已有的 state.json,只覆写 stage 字段;解析失败才退回 created(quality)


其他(较次要,可顺带处理)

  • src-tauri/src/process/mod.rs:207-230:Windows 下先 spawnAssignProcessToJobObject,这个窗口内子进程派生的孙进程会逃出 Job,取消时可能残留。彻底修需 CREATE_SUSPENDED;短期可把 Job 创建提前,并在取消分支补 child.wait().await
  • src-tauri/src/engines/ffprobe.rs:17probe_video 自建 ProcessManager::new(),导致探测阶段无法被取消。
  • src-tauri/src/pipeline/runner.rs:752best_sparse_model 在 async 上下文里使用阻塞 std::fs::read_dir
  • src/app/App.tsx:220:靠 message.includes("取消") 判断取消状态,依赖错误文案,建议结构化错误码。
  • src/lib/backend.ts:22checkColmapAcceleration 缺少 inTauri() 守卫,与同文件其他函数不一致。
  • src-tauri/src/project/catalog.rs:236:只要 final.ply 存在就强制标记 Completed,会把「训练成功但发布失败」的项目误标为完成。

环境

  • 版本:0.2.0
  • 方式:源码静态走查,未运行端到端流水线

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions