Skip to content

Bowl: IPC 架构缺陷、功能闭环断裂及平台可用性审查 #492

Description

@JusterZhu

问题概述

GeneralUpdate.Bowl 组件进行代码审查后,发现以下架构层面和功能层面的问题。


🔴 严重问题

1. UpgradeFail 版本排除机制自毁

IpcEncryption.DecryptFromFile 在每次读取后自动删除文件:

finally {
    try { File.Delete(filePath); } catch { }
}

流程:

  1. Bowl 检测到崩溃 → SetVariable("UpgradeFail", "2.0.0") → 写入 %TEMP%/GeneralUpdate/ipc/UpgradeFail.enc
  2. Core CheckFail() 调用 GetEnvironmentVariable("UpgradeFail") → 解密 → 返回 "2.0.0" → 文件被删除
  3. 再次调用 CheckFail() → 文件不存在 → 返回空字符串 → 跳过版本排除 → 再次安装已知崩溃版本

WindowStrategy.SetEnvironment() 注释声明:

"Once this version number is set, it will not be removed, and updates will not proceed until a version greater than the exception version number is obtained."

这是一个 永久性版本排除机制,但实现上只能工作一次。

2. Bowl 与 Core 之间 Environments + IpcEncryption 源码完全重复

Bowl Core
Bowl/Ipc/IpcEncryption.cs Core/Ipc/IpcEncryption.cs
Bowl/Ipc/Environments.cs Core/Configuration/Environments.cs

相同的 AES 密钥、相同的文件路径、逐字复制的代码。任何一方的密钥/路径变更未同步都会导致 IPC 静默失败。

3. Bowl 启动时读不到 ProcessInfo

WindowsStrategy.StartAppAsync() 直接 Process.Start(bowlAppPath)没有先写入 ProcessInfo 环境变量。Bowl 的 CreateParameter() 读取 ProcessInfo 失败 → ArgumentNullException → Bowl 进程直接退出。


🟡 中等问题

4. macOS 策略 (MacBowlStrategy) 在生产环境不可用

策略自身注释承认:

"lldb requires the process being debugged to allow debugging (SIP / task_for_pid restrictions). For production macOS crash capture, consider using Crashpad instead."

which lldb 检查只能确认 lldb 存在,不能确认它能 attach 目标进程。在生产 macOS 启用了 SIP 的情况下策略是一个空壳。

5. Linux 策略仅支持部分发行版

  • 仅支持 6 个发行版:ubuntu/debian/rhel/centos/fedora/clearos
  • 所有包名只有 x86_64,ARM64(树莓派、AWS Graviton)全不支持
  • install.sh 依赖 sudo 且无密码提示处理 — 挂起 60s 直到超时

6. Linux 策略 -p 仅接受 PID

Linux procdump -p 只接受数字 PID,但参数名叫 ProcessNameOrId。开发者传进程名时静默失败。

7. 未使用的 CrashJsonContext 源码生成器

CrashJsonContext 定义了 [JsonSerializable(typeof(Crash))],但 CrashReporter 使用的是 JsonSerializer.Serialize(obj)(反射模式),源码生成器完全未用。

8. WindowsSystemInfoProvider 同步阻塞无取消支持

ExportAsync(string outputDirectory, CancellationToken ct) 方法内 process.WaitForExit(30_000) 同步阻塞,ct 从未被检查或使用。

9. ProcessRunner 输出竞态条件

OutputDataReceived 在 ThreadPool 线程触发,进程退出后可能仍有事件未完成。Exited 事件触发和 lock 拿快照之间有窗漏。


🔵 低优先级

10. Strategies/ vs Strategys/ 命名空间混淆

新 API(Strategies/IBowlStrategy)和旧 [Obsolete] API(Strategys/IStrategy)并存,"Strategys" 拼写错误。

11. TextTraceListener 位于全局命名空间

public class TextTraceListener : TraceListener — 没有 namespace 声明,污染所有消费者的全局命名空间。

12. StorageHelper 暴露为 public

内部文件系统工具类作为 public static class 暴露,应改为 internal

13. GeneralTracer.Fatal 使用错误的 TraceLevel

public static void Fatal(string message) => WriteTraceMessage(TraceLevel.Off, message);

TraceLevel.Off 意为"不输出任何消息",对 Fatal 日志语义错误。


审查结论

  • Windows: 完整功能可用
  • Linux: 仅在满足 4 个条件时可工作(发行版在支持列表、sudo 免密、目标为 PID、procdump 版本兼容),无系统诊断导出
  • macOS: 实际不可用

修复 PR

PR #491 解决了上述问题中的 1–8, 10–12。

Metadata

Metadata

Assignees

Labels

refactorRefactor some existing code.

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions