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

No fields configured for Task.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions