Skip to content

xtask: re-sign binaries after pdump fingerprint patch on macOS#91

Merged
eval-exec merged 1 commit into
eval-exec:mainfrom
Kinneyzhang:fix/macos-codesign-after-pdump-patch
May 3, 2026
Merged

xtask: re-sign binaries after pdump fingerprint patch on macOS#91
eval-exec merged 1 commit into
eval-exec:mainfrom
Kinneyzhang:fix/macos-codesign-after-pdump-patch

Conversation

@Kinneyzhang
Copy link
Copy Markdown
Contributor

Problem

On macOS (Apple Silicon), cargo xtask fresh-build --release fails with:

error: command failed with status signal: 9 (SIGKILL):
  neomacs-temacs --batch -l loadup --temacs=pbootstrap

Root Cause

The patch_primary_executable_fingerprint step modifies the executable binary in-place to embed the pdump fingerprint. On macOS, any in-place modification of a signed binary invalidates its code signature. When the kernel subsequently tries to execute the binary, it detects the invalid signature and sends SIGKILL.

Fix

After copy_executable_role_images copies the patched final_bin to the temacs and bootstrap roles, re-sign all three binaries using an ad-hoc signature (codesign --force --sign -). Ad-hoc signing requires no certificate and is sufficient for local execution.

This fix is gated behind #[cfg(target_os = macos)] and has no effect on Linux builds.

Patching the pdump fingerprint modifies the executable image in-place,
which invalidates the macOS code signature.  Without a valid signature
the kernel sends SIGKILL (signal 9) when the binary is executed during
the pbootstrap and pdump steps.

After copy_executable_role_images copies the patched final_bin to the
temacs and bootstrap roles, re-sign all three binaries with an ad-hoc
signature (codesign --sign -) so the kernel accepts them.

Fixes build failure on Apple Silicon:
  error: command failed with status signal: 9 (SIGKILL):
    neomacs-temacs --batch -l loadup --temacs=pbootstrap
Copilot AI review requested due to automatic review settings May 3, 2026 13:06
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a macOS-specific build step to re-sign role binaries after patching the pdump fingerprint, which is necessary to prevent execution failures due to invalid code signatures. The review feedback highlights several improvement opportunities: ensuring the new logic respects the dry run flag, utilizing the project's existing command execution helpers for consistent logging and error handling, and improving path handling to avoid potential panics.

Comment thread xtask/src/main.rs
Comment on lines +389 to +407
// macOS: re-sign all role binaries after patching. Patching the pdump
// fingerprint modifies the executable image in-place, which invalidates
// the code signature. Without a fresh ad-hoc signature the kernel sends
// SIGKILL when the binary is executed (exit status: signal 9).
#[cfg(target_os = "macos")]
{
for bin in [&paths.temacs, &paths.bootstrap, &paths.final_bin] {
if bin.exists() {
let status = std::process::Command::new("codesign")
.args(["--force", "--sign", "-", bin.to_str().unwrap()])
.status()?;
if !status.success() {
return Err(
format!("codesign failed on {}", bin.display()).into()
);
}
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation for re-signing binaries on macOS has a few issues that should be addressed to maintain consistency with the rest of the build pipeline:

  1. Dry Run Support: It does not respect the options.dry_run flag. A dry run should print the commands that would be executed without actually running them. Currently, this block either executes the command or does nothing, without informing the user.
  2. Consistency: The project uses a run_command helper (line 2334) to manage external process execution, including logging and error reporting. Bypassing it here leads to inconsistent output and error handling.
  3. Robustness: Using bin.to_str().unwrap() is risky as it will panic if a path contains invalid UTF-8. Using OsString via the run_command interface is safer and more idiomatic in Rust.

Leveraging the existing helpers will resolve these issues and ensure the build script behaves predictably.

    // macOS: re-sign all role binaries after patching.  Patching the pdump
    // fingerprint modifies the executable image in-place, which invalidates
    // the code signature.  Without a fresh ad-hoc signature the kernel sends
    // SIGKILL when the binary is executed (exit status: signal 9).
    #[cfg(target_os = "macos")]
    {
        let codesign = tool_program("codesign");
        for bin in [&paths.temacs, &paths.bootstrap, &paths.final_bin] {
            if options.dry_run || bin.exists() {
                run_command(
                    options,
                    &options.repo_root,
                    &codesign,
                    &[
                        OsString::from("--force"),
                        OsString::from("--sign"),
                        OsString::from("-"),
                        bin.as_os_str().to_os_string(),
                    ],
                    &[],
                )?;
            }
        }
    }

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the xtask fresh-build pipeline on macOS so patched role binaries are re-signed after the pdump fingerprint is embedded, addressing the Apple Silicon SIGKILL failure caused by invalidated code signatures.

Changes:

  • Add a macOS-only re-signing step after patching/copying the role executables.
  • Re-sign temacs, bootstrap, and the final binary with ad-hoc codesign.
  • Keep Linux behavior unchanged via #[cfg(target_os = "macos")].

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread xtask/src/main.rs
Comment on lines +395 to +403
for bin in [&paths.temacs, &paths.bootstrap, &paths.final_bin] {
if bin.exists() {
let status = std::process::Command::new("codesign")
.args(["--force", "--sign", "-", bin.to_str().unwrap()])
.status()?;
if !status.success() {
return Err(
format!("codesign failed on {}", bin.display()).into()
);
Comment thread xtask/src/main.rs
for bin in [&paths.temacs, &paths.bootstrap, &paths.final_bin] {
if bin.exists() {
let status = std::process::Command::new("codesign")
.args(["--force", "--sign", "-", bin.to_str().unwrap()])
Copy link
Copy Markdown
Owner

@eval-exec eval-exec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@eval-exec eval-exec merged commit 04f2ed6 into eval-exec:main May 3, 2026
3 of 4 checks passed
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.

3 participants