Skip to content

fix: 修复QGA资源泄漏、strip CSI逻辑缺陷、atomic race等8项问题#167

Open
TonyTsang81 wants to merge 12 commits into
harmoninux:masterfrom
TonyTsang81:master
Open

fix: 修复QGA资源泄漏、strip CSI逻辑缺陷、atomic race等8项问题#167
TonyTsang81 wants to merge 12 commits into
harmoninux:masterfrom
TonyTsang81:master

Conversation

@TonyTsang81

Copy link
Copy Markdown

修复内容

BLOCKING

  • QGA resize try-finally 确保 agent release(资源泄漏)
  • stripEchoedCsi partial match 修复(重复扫描)

MAJOR

  • 统一 CSI strip 逻辑,删除 JS 重复代码
  • atomic TSFN load 一次消除 race window
  • port mapping filter 明确 null/undefined 检查

MINOR

  • socket unlink 加 hilog.warn
  • VncPage pendingSurface 初始化改 -1

验证

  • Build: ✅ BUILD SUCCESSFUL
  • 设备运行: ✅ Ubuntu 26.04 LTS 正常启动

🤖 Generated with Claude Code

TonyTsang81 and others added 8 commits June 16, 2026 00:45
1. QemuMonitor: setInterval未清理 → 组件销毁后定时器向已关闭Socket发数据
2. EntryAbility: getEmulatorToStart() 空指针断言 → 找不到匹配模拟器时NPE
3. WebTerminal: Native回调泄漏 → 缺少aboutToDisappear生命周期清理
4. napi_vnc: TSFN竞态 → napi_tsfn_release 改 napi_tsfn_abort 防use-after-free
Added port availability check before launching QEMU with -vnc.
When VNC port is occupied, auto-finds free port in 5900-5999 range.
When all ports are full, falls back to serial-only mode.
Fixes SIGABRT from QEMU vnc_init_func exit(1) on port bind failure.
- 删除 QemuMonitor.ets (2s QMP死循环轮询, build()为空, 未被任何页面引用)
- VmStatusBar: 移除 aboutToAppear 中强写 masterSwitch=true, 用户开关真正生效
- QemuAgent: 新增 getSystemInfo() 一次 shell exec 获取 meminfo+cpu stats+ssh
  替代原来三次独立调用, 每次刷新 QGA 往返从~15s降至~3s
- 附带 QemuAgent 锁重写(promise链→队列锁), WebTerminal清屏debounce, 关机超时等修复
- 新增 Nerd Font 字体资源
- EntryAbility: skip privileged ports (<1024) to avoid system security policy SIGKILL
- startVm: disable VNC when portMapping > 4 to prevent fd exhaustion in QEMU vnc_init_func
- EditEmulatorContent: 移除 cd /Users/t_tsang/DevecostudioProjects/HiSH && git add -A && git diff --cached --stat 非空断言,添加 null 守卫防止镜像删除后崩溃
- ImageManagementContent: 补充 modeNames 缺少的 cleanup 键;virtualSize 除零保护
- SharedFolderContent: 用 fileUri.FileUri 安全提取文件名替代 split 解析;统一 hilog DOMAIN
- VmStatusBar: getContext(this) 位于 build() 内非 @builder,确认为安全误报
- Napi: 新增 Utils 类包装字符串/开关 IPC 调用,修复返回类型
- 字符串资源: zh_CN/base 新增 msg_rootfs_not_found
- Settings: 格式化及实验性功能界面优化
- C++: 修复 napi_init/utils 兼容性
- BLOCKING: QGA resize try-finally 确保 agent release
- BLOCKING: stripEchoedCsi partial match 修复
- MAJOR: 统一 CSI strip 逻辑(删除 JS 重复)
- MAJOR: atomic TSFN load 一次消除 race window
- MAJOR: port mapping filter 明确 null/undefined 检查
- MINOR: socket unlink 加 hilog.warn
- MINOR: VncPage pendingSurface 初始化改 -1

Co-Authored-By: Claude <noreply@anthropic.com>
P0 修复:
- QemuAgent.disconnect() 导致 Promise 永久挂起(新增 responseReject)
- Checkbox 双重触发(移除 onClick,只保留 onChange)
- sendInput TOCTOU(fd 只 load 一次)

P1 修复:
- 抽取 auto-snapshot 重复逻辑(lib/autoSnapshot.ets)
- 修复缺失字体的 @font-face(SourceCodePro)
- 移除无文件的 Cascadia/JetBrains/Fira 字体

P2 修复:
- 移除 USB 冗余参数(usb=on 已足够)

清理:
- 删除 rawfile/font/ 目录(58MB,完全无引用)
- 删除 .DS_Store 文件并加入 .gitignore
- 统一字体选项(fontOptions / FONT_LIST / isFontCustom)
BLOCKING 修复:
- stripEchoedCsi 跨 buffer partial match 状态维护
- onShutdown TSFN 双重 load race window
- applyCustomTheme background 硬编码修复

新功能:
- LauncherPage 启动固件选择页(倒计时自动启动)
- SnippetsPanel 命令面板(添加/编辑/删除/收藏)
- 虚拟键集成 COMM 按钮(打开命令面板)
- 虚拟键新增 | (pipe) 按钮

耗电优化:
- TCG tb-size 2048→512
- IO poll-max-ns 2000000→500000
- 串口 poll 自适应(10ms→500ms)
- 内核参数:nohz=on, clocksource=arch_sys_counter

其他:
- appOption 新增 showLauncher/lastEmulatorId 配置
- Emulator 模型新增 Snippet 接口
- SettingsContent 新增启动选择页开关
@TonyTsang81

Copy link
Copy Markdown
Author

PR #167 最终审查报告

PR: harmoninux/HiSH#167
规模: 44 files, +2706 / −459
审查日期: 2026-06-26(最终轮)


上一轮 3 个 BLOCKING — 全部修复 ✅

问题 修复方式
CSI partial match 新增 csi_partial_buf + csi_partial_len 静态缓冲区,拼接跨 poll 边界的残缺序列
TSFN 双重 load auto cb = on_shutdown_callback.load(...) 单次 load
background 硬编码 改为 this.customBg

🆕 本轮新增功能

LauncherPage(启动固件选择页)

pages/LauncherPage.ets — 336 行,全新页面

流程

打开 App → EntryAbility 检查 showLauncher
  ├── true  → 加载 LauncherPage → 显示 VM 卡片列表 → 3 秒倒计时自动启动上次的
  │             ├── 点其他 VM → 取消倒计时,立即启动
  │             └── 点"跳过" → 手动选择
  └── false → 直接加载 Index → 启动默认 VM(和原来一样)

亮点

  • main_pages.json 注册了新路由 ✅
  • 设置页有 Toggle 开关控制 showLauncher
  • lastEmulatorId 记录上次启动,倒计时默认选它 ✅
  • doStartVm 逻辑复用了 EntryAbility 的 VM 启动代码(包括性能预设、VNC 端口预检)✅

小建议

  • emulators.length <= 1 时直接跳过 Launcher 是对的,但如果用户只有 1 个 VM 但想看看,可以改为 <= 0 才跳过。不过这个属于偏好,可改可不改。

SnippetsPanel(命令面板)

components/SnippetsPanel.ets — 309 行,全新组件

功能

  • 半屏面板 + 下拉把手
  • 搜索过滤 (label + command 双重匹配)
  • 收藏 (starred) 排序
  • 添加/编辑/删除命令(弹窗编辑)
  • 长按删除、点一下发送

数据模型

interface Snippet {
  id: string
  label: string      // "更新软件包"
  command: string    // "apt update -y && apt upgrade -y\n"
  starred: boolean
  sortOrder: number
}

存储在 Emulator.snippets 里,默认 6 条预设命令。

集成

  • WebTerminal 右下角浮动 ⚡ 按钮 → 弹起 SnippetsPanel
  • 点击命令 → this.sendInput(cmd) → 面板自动收起
  • 所有 CRUD 操作直接写回 AppStorage.emulators

小建议

  • onToggleStar 回调传入了但 SnippetsPanel 内部没有对应的 UI 触发点。如果要支持点击 ⭐ 切换收藏,需要在列表项的 Row 里加一个可点击的 Star 图标。目前只能通过编辑来变 starred。(如果暂时不需要这个功能,回调可以删掉避免死代码)

耗电优化

startVm.ets 两行改动:

参数 改前 改后
tb-size 2048 512
poll-max-ns 2000000 500000

Preferences 批量写入 + debounce

appOption.ets 重构:

  • 类名 appOptionAppOption(大写),所有字段加 readonly
  • 新增 showLauncherlastEmulatorId 等键
  • savePreference 改为 Map 收集 + 50ms debounce + 批量 flush
  • Preferences 实例缓存,避免重复 getPreferences

⚠️ 新发现

1. LauncherPage 与 EntryAbility 的 VM 启动逻辑重复

LauncherPage.doStartVm()EntryAbility.startDefaultEmulator() 是两套几乎一样的代码(VNC 端口预检、性能预设、端口过滤)。如果未来改 VM 启动参数,需要改两个地方。

建议:把 doStartVm 抽到 lib/startVm.ets 里的一个共享函数,LauncherPage 和 EntryAbility 都调它。

2. Snippets 编辑时 starred 不可改

编辑弹窗只有 label 和 command 两个输入框,没办法切换 starred 状态。如果要让用户能收藏/取消收藏,需要在编辑弹窗加一个 Checkbox。


✅ 做得好的地方

改动 评价
3 个 BLOCKING 全部修复 质量高,尤其 CSI buffer 拼接方案
LauncherPage 路由设计 EntryAbility 判断 showLauncher 决定首屏,干净
Snippets 数据跟 Emulator 走 不引入新的持久化层,架构简洁
耗电两行参数 影响小风险低,先试了再说
Preferences debounce 50ms 批量写入避免高频 IO
DEFAULT_SNIPPETS 预设 6 条 开箱即用

总评

类别 数量 状态
🔴 BLOCKING 0 ✅ 全部修复
🟡 可改进 2 代码重复 + star UI
🟢 MINOR 0

结论:PR 可以提请上游 review 了。核心并发修复正确,新增功能(启动页 + Snippets + 耗电优化)设计合理,代码量和侵入度匹配。代码重复和 star UI 这两个可以在后续迭代中处理。

TonyTsang81 and others added 4 commits June 26, 2026 17:34
- DEFAULT_SNIPPETS 从6条增至15条
- 编辑模式按钮从符号改为文字(删除/编辑)
- loadSnippets 首次自动填充预设命令
- QemuAgent: responseTimer ≤0 边界 + 超时后清除 responseResolve
- napi_init: idle_count 溢出保护(上限 10000)
- appOption: flush 期间写入 snapshot 防丢失
- QemuAgent 新增 onDisconnect 回调
- Socket close 事件触发回调,Manager 立即尝试重连
- 不再依赖 20s 心跳才发现断线
- module.json5: 加 ohos.permission.RUNNING_LOCK 权限 (system_grant)
- backgroundRunningManager: 改用 @ohos.runningLock API (create + hold/unhold)
- EntryAbility: VM 启动时按 keepAwake 设置申请 running lock
- WebTerminal/EmulatorListGrid: VM 关机时释放 running lock
- SettingsContent: 加「保持 CPU 唤醒」开关 (默认开启)
- string.json: 加中英文字符串资源
- appOption: 加 keepAwake 选项 key

Co-Authored-By: Claude <noreply@anthropic.com>
@hackeris

Copy link
Copy Markdown
Member

master也支持了“字体”相关的功能,目前有冲突。另外,这个PR能否拆成多个,每个只解决一项具体的问题。

现在这个PR有点大,内容很多,而且有冲突,review和合并都非常困难

@TonyTsang81

Copy link
Copy Markdown
Author

明白的,我这边也是在使用过程中发现的问题和痛点,然后就顺手让claude改一下,没有想太多。这些都是在一天内改的,现在拆可能有点麻烦。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants