Skip to content

fix(install): bail on missing binary when writing macOS app bundle - #1872

Open
wignerStan wants to merge 1 commit into
BigPizzaV3:mainfrom
wignerStan:fix/macos-empty-bundle
Open

fix(install): bail on missing binary when writing macOS app bundle#1872
wignerStan wants to merge 1 commit into
BigPizzaV3:mainfrom
wignerStan:fix/macos-empty-bundle

Conversation

@wignerStan

Copy link
Copy Markdown

概述 (Summary)

Fixes #1871: macOS 安装/修复流程可能生成"空壳".app bundle(只有 sh 包装脚本、没有真实二进制),导致管理工具点击无法启动且全程无声。

根因 (Root cause)

crates/codex-plus-core/src/install/macos.rswrite_bundle 静默跳过二进制拷贝:

  1. source.exists() 为 false → 跳过拷贝,仍返回 Ok(()),UI 报"已安装/已修复"
  2. source == &target(自修复场景)→ 跳过拷贝,且不校验目标

生成空壳后,exec "$DIR/codex-plus-plus-manager" 找不到二进制,点击图标静默失败(无窗口、无日志)。

改动 (Changes)

crates/codex-plus-core/src/install/macos.rs

write_bundle 现在会明确报错(bail!):

  • 缺少 binary_source / binary_target_name 信息
  • 二进制源不存在(提示从 DMG 重装)
  • 二进制源是 sh 脚本(#! 开头)——识别"包装脚本当二进制源"场景
  • source == target 但目标缺失或非真实二进制(自修复 no-op 防护)

新增辅助函数:

  • is_shell_script(path):读取文件头判断 #!
  • is_real_binary(path):判断 size > 1KB 且非目录

install_binary_source 增强:

  • sidecar 缺失时,若 target 为 .、缺失或为 sh 脚本,回退到 current_exe() 同目录 companion 二进制(非脚本),降低把包装脚本当源的概率

验证 (Verification)

注意:本环境无 Rust 工具链,代码未经编译/测试。 需在 CI 或有 cargo 的环境运行:

cargo fmt --all -- --check
cargo test -p codex-plus-core
cargo build --release

现场验证(用户机器,未覆盖于本 PR)

从 DMG 恢复真实二进制到两个 bundle 后,强杀 → 再次点击启动 → 进程存活、守卫端口 57319 LISTEN、日志出现 manager.start,强杀→重启闭环通过。

相关文档

报告:docs/reports/2026-08-17-macos-bundle-empty-shell-修复报告.md

write_bundle silently skipped copying the real binary when:
- binary_source did not exist, or
- binary_source == target (self-repair from inside the bundle)

Both cases produced a bundle containing only the ~100-byte sh wrapper,
so clicking the app icon exec'd a missing binary and failed silently
with no window, no log, no error. install_entrypoints/repair_entrypoints
still reported success.

Now write_bundle errors out when the source is missing, when the source
is a shell script rather than a real binary, or when source == target
but the target is not a real binary. install_binary_source also falls
back to the current_exe companion binary when the target resolves to
'.' or a shell script.

Fixes: empty-shell macOS app bundles after install/repair
@BigPizzaV3

BigPizzaV3 commented Aug 18, 2026

Copy link
Copy Markdown
Owner

感谢排查。这个问题已经在最新 main307aae9 中处理:write_bundle 现在会在复制前后调用 validate_binary_source,明确拒绝不存在、非普通文件、过小或以 #! 开头的二进制,也不会再把空壳 bundle 当作安装成功。

当前 PR 与最新 maincrates/codex-plus-core/src/install/macos.rs 已冲突,核心修复没有独立增量,因此不建议直接合并。如果这里还有 307aae9 未覆盖的具体安装路径,请基于最新 main 单独拆出并补对应测试。

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.

macOS: install/repair can produce empty-shell .app bundles (manager fails to launch silently)

2 participants