fix(perry-ffi): unbreak cargo test -p perry-ffi link on Linux (cargo-test gate)#5089
fix(perry-ffi): unbreak cargo test -p perry-ffi link on Linux (cargo-test gate)#5089proggeramlug wants to merge 1 commit into
cargo test -p perry-ffi link on Linux (cargo-test gate)#5089Conversation
…break cargo-test link on Linux PR #5083 added the perry-runtime hook js_register_ffi_handle_exists_probe, declared as an extern "C" in handle.rs and called from register_handle via ensure_handle_exists_probe_registered. The perry-ffi lib-test binary does not link perry-runtime, so the symbol is undefined; because the unit tests call register_handle, the reference survives --gc-sections and Linux ld fails the link (the cargo-test CI gate). macOS resolves it lazily, hiding it locally. Split the probe out of the shared extern block: keep the extern declaration under #[cfg(not(test))] (production, unchanged) and add a #[cfg(test)] #[no_mangle] no-op definition so the lib-test binary has a local symbol. Production codegen is byte-identical. cargo test -p perry-ffi now passes.
📝 WalkthroughWalkthroughThis release pins a Linux linker failure in perry-ffi by adding a test-time no-op stub for the missing ChangesFFI Link Fix and Release v0.5.1165
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CHANGELOG.md`:
- Around line 1-26: Remove the contributed CHANGELOG entry titled "v0.5.1165 —
fix(perry-ffi): unbreak the `cargo test -p perry-ffi` link on Linux" from the PR
by reverting the edits to CHANGELOG.md that add that paragraph; leave the file
as it was in the base branch so maintainers can add release notes at merge time.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: e36e1bc3-0867-4c5e-860f-8f909625baab
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (4)
CHANGELOG.mdCLAUDE.mdCargo.tomlcrates/perry-ffi/src/handle.rs
| ## v0.5.1165 — fix(perry-ffi): unbreak the `cargo test -p perry-ffi` link on Linux | ||
|
|
||
| The `cargo-test` CI gate started failing after v0.5.1164 (#5083, the http2 | ||
| `server.close()` timer-id collision fix). That PR added a perry-runtime hook, | ||
| `js_register_ffi_handle_exists_probe`, declared as an `extern "C"` in | ||
| `crates/perry-ffi/src/handle.rs` and called from | ||
| `ensure_handle_exists_probe_registered`, which `register_handle` invokes | ||
| lazily on first handle creation. | ||
|
|
||
| In the real `perry` binary the symbol resolves because perry-runtime is always | ||
| linked in. But the **`perry-ffi` lib-test binary does not link perry-runtime**, | ||
| so the symbol is undefined there. `perry-ffi`'s unit tests (`round_trip_simple_value`, | ||
| `handles_are_unique`, …) all call `register_handle`, so the probe call sits on | ||
| a test-reachable path and survives `--gc-sections`. On Linux `ld` an undefined | ||
| reference is a hard link error (`undefined reference to | ||
| 'js_register_ffi_handle_exists_probe'`), aborting the gate. macOS's linker | ||
| resolves it lazily, so it passed locally. The crate's other runtime hooks | ||
| (`perry_ffi_gc_register_*`) stay undefined harmlessly: no test-reachable code | ||
| calls them, so the linker drops their references. | ||
|
|
||
| Fix: split the probe out of the shared `extern "C"` block into a | ||
| `#[cfg(not(test))]` extern declaration (production, unchanged) plus a | ||
| `#[cfg(test)] #[no_mangle]` no-op definition that gives the lib-test binary a | ||
| local symbol to link against. Production codegen is byte-identical; only the | ||
| test binary gains the stub. `cargo test -p perry-ffi` now links and passes | ||
| (13 tests). |
There was a problem hiding this comment.
Please drop this changelog entry from the contributor PR.
This repo’s release policy says external contributor PRs should not edit CHANGELOG.md; maintainers add the release note at merge time.
Based on learnings, external contributor PRs should not touch CHANGELOG.md; maintainers bump version and write the changelog at merge time.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@CHANGELOG.md` around lines 1 - 26, Remove the contributed CHANGELOG entry
titled "v0.5.1165 — fix(perry-ffi): unbreak the `cargo test -p perry-ffi` link
on Linux" from the PR by reverting the edits to CHANGELOG.md that add that
paragraph; leave the file as it was in the base branch so maintainers can add
release notes at merge time.
Source: Learnings
|
Closing as a duplicate of #5088, which was opened first and fixes the same #5088's gating is also more correct: it stubs the symbol under |
Problem
The
cargo-testCI gate has been red since v0.5.1164 / #5083 (the http2server.close()timer-id collision fix). Every PR opened againstmainsince then failscargo-test.The failure is a link error, not a test assertion:
Root cause
#5083 added a perry-runtime hook,
js_register_ffi_handle_exists_probe, declared as anextern "C"incrates/perry-ffi/src/handle.rsand called fromensure_handle_exists_probe_registered, whichregister_handleinvokes lazily on first handle creation.perrybinary the symbol resolves — perry-runtime is always linked in.perry-ffilib-test binary does not link perry-runtime, so the symbol is undefined there. perry-ffi's unit tests (round_trip_simple_value,handles_are_unique, …) all callregister_handle, so the probe call is on a test-reachable path and survives--gc-sections. Linuxldtreats the undefined reference as a hard error and aborts the gate.cargo test -p perry-ffipassed locally and the regression slipped through.The crate's other runtime hooks (
perry_ffi_gc_register_*) stay undefined harmlessly: no test-reachable code calls them, so the linker drops their references.Fix
Split the probe out of the shared
extern "C"block:#[cfg(not(test))]extern declaration — production, unchanged (byte-identical codegen).#[cfg(test)] #[no_mangle]no-op definition — gives the lib-test binary a local symbol to link against.The
cfg(test)stub only applies when perry-ffi is the crate under test; when perry-ffi is built as a dependency for another crate it uses the extern declaration, so there's no duplicate-symbol risk against the real perry-runtime definition.Validation
cargo test -p perry-ffi→ 13 passed (was: link error).cargo build -p perry-ffi(non-test) clean, no warnings.cargo fmtclean.Version bumped to 0.5.1165 with a CHANGELOG entry per the workflow.
Summary by CodeRabbit
Bug Fixes
Chores