Skip to content

ci: test ZDebug on the PHP 8.6 beta via z-engine 8.6.x-dev - #24

Draft
lisachenko wants to merge 5 commits into
mainfrom
claude/zdebug-php-8.6-testing-2pwowy
Draft

lisachenko wants to merge 5 commits into
mainfrom
claude/zdebug-php-8.6-testing-2pwowy

Conversation

@lisachenko

@lisachenko lisachenko commented Aug 29, 2026 •

Copy link
Copy Markdown
Owner

What

z-engine's master supports PHP 8.6 (branch-aliased 8.6.x-dev, with linux and darwin x64/arm64 definitions committed — lisachenko/z-engine#58, lisachenko/z-engine#278), so ZDebug is tested on the 8.6 beta the same way it rides the 8.4 and 8.5 lines.

  • composer.json — z-engine constraint widened to 8.4.x-dev || 8.5.x-dev || 8.6.x-dev. The platform php requirement of each z-engine line still makes Composer resolve the matching branch per running PHP minor (verified with dry runs on 8.4 and 8.5 — they keep picking 8.4.x-dev / 8.5.x-dev).
  • CI — PHP 8.6 legs added to the tests matrix on ubuntu-latest, macos-latest (arm64) and macos-15-intel (x64), and to the PHPStan matrix. All legs required — no experimental escapes.
  • docs — README badge/requirements and AGENTS.md branch model extended to 8.4 / 8.5 / 8.6 (beta).

History: the macOS arm64 + PHP 8.6 corruption

The first arm64+8.6 runs crashed every instrumented debuggee: Apple Silicon clang builds of PHP 8.6 selected the new tail-call VM (ZEND_VM_KIND_TAILCALL), under which user opcode handlers mis-resumed execution (reproduced with pure ext-ffi code, no zdebug/z-engine involved). Diagnosed in lisachenko/z-engine#280, filed upstream as php/php-src#24081, fixed by php/php-src#24109 (merged into PHP-8.6). The leg ran as continue-on-error during the ~6 weeks the bug was live and is required again since the fix.

Verification

Local (PHP 8.6 NTS linux-x64, z-engine 8.6.x-dev):

  • composer test — OK, 291 tests, 1916 assertions
  • composer test:integration (--fail-on-skipped) — OK, 41 tests, 782 assertions, none skipped
  • composer phpstan (level max) — no errors
  • composer cs:check — clean

CI: full matrix across ubuntu / macOS x64 / macOS arm64 on 8.4, 8.5 and 8.6.

claude added 3 commits August 29, 2026 12:58
z-engine master supports PHP 8.6 (branch-aliased 8.6.x-dev) with linux
and darwin definitions committed, so ZDebug can ride it the same way it
rides 8.4.x-dev and 8.5.x-dev:

- composer: accept lisachenko/z-engine 8.6.x-dev; Composer picks the
  matching line per running PHP minor as before
- ci: add PHP 8.6 legs on ubuntu-latest, macos-latest (arm64) and
  macos-15-intel (x64) to both the test and PHPStan matrices
- docs: extend the supported-version wording to 8.4 / 8.5 / 8.6 (beta)

Verified locally on PHP 8.6.0beta2 (NTS): full suite (291 tests) and
the integration gate (41 tests, fail-on-skipped) green, PHPStan level
max clean, cs check clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U4cKi87mVQ896uSrw592fG
The Tests (PHP 8.6, macos-latest) leg fails with child crashes (exit 11)
and corrupted function dispatch while the identical PHP build passes on
macos-15-intel, and z-engine's own arm64 8.6 suite is green. This
manually-dispatched workflow layers the boot sequence (Core::init ->
EXT_STMT compile -> opcode handlers -> module registration -> full
zdebug boot) on both 8.5 (control) and 8.6, and captures an lldb
backtrace of the crash. Will be removed once the failure is root-caused.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U4cKi87mVQ896uSrw592fG
workflow_dispatch workflows on a non-default branch cannot be dispatched,
so the temporary diagnostic job runs with the PR's CI instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U4cKi87mVQ896uSrw592fG
…tics

The layered diagnostic run (see the removed diagnose job in the previous
commits) isolated the arm64 failure to z-engine itself: with
COMPILE_EXTENDED_STMT on, the first EXT_STMT dispatch through a user
opcode handler already corrupts VM state (a by-ref closure counter reads
back as a ZEngine\Core object), and instrumented debuggees segfault in
ZEND_DO_UCALL_SPEC_RETVAL_USED_TAILCALL_HANDLER. Apple Silicon clang
builds of PHP 8.6 select the new tail-call VM (ZEND_VM_KIND_TAILCALL);
x64 clang and gcc keep the hybrid VM, which is why linux and macOS x64
are green on the same PHP source. PHP 8.5 on the same arm64 runner
passes every probe.

Reported upstream as lisachenko/z-engine#280. The arm64 8.6 leg keeps
running as continue-on-error for visibility and becomes required again
once the upstream issue is resolved; README/AGENTS note the platform
exception.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U4cKi87mVQ896uSrw592fG

Copy link
Copy Markdown
Owner Author

Root cause of the Tests (PHP 8.6, macos-latest) failure — upstream, not this PR's. The first run failed only on macOS arm64 + 8.6 (Ubuntu, macOS x64 and PHPStan were green on the same PHP build). A temporary layered diagnostic job (commits db23e9c/a1e7404, removed again in d8ec2f3) isolated it to z-engine itself, with no zdebug code involved:

  • Core::init() alone ✅, COMPILE_EXTENDED_STMT alone ✅
  • adding a bare OpCode::setHandler(EXT_STMT, …) ❌ — the handler closure's own by-ref counter reads back as a ZEngine\Core object on the first dispatch (Cannot increment ZEngine\Core), and a full zdebug boot segfaults in ZEND_DO_UCALL_SPEC_RETVAL_USED_TAILCALL_HANDLER (KERN_INVALID_ADDRESS at 0x10)
  • the identical probes on PHP 8.5 on the same arm64 runner all pass

The TAILCALL handler names are the tell: Apple Silicon clang builds of PHP 8.6 select the new tail-call VM (ZEND_VM_KIND_TAILCALL, new in 8.6), while x64 clang and gcc keep the hybrid VM — which is exactly the failing-platform boundary. Filed upstream with a minimal repro as lisachenko/z-engine#280.

Since no fix exists yet, this PR now runs the arm64+8.6 leg as continue-on-error: true with a comment pointing at #280 (so it stays visible and flips back to required once upstream is fixed), and README/AGENTS note the platform exception. Everything else — linux-x64 and macOS x64 on 8.6, plus the full 8.4/8.5 matrix — is green and required.


Generated by Claude Code

… fixed

php-src fixed the user-opcode dispatch under the tail-call VM
(lisachenko/z-engine#280, resolved by php/php-src#24109 merged into
PHP-8.6), and current 8.6 nightlies run engine hooks cleanly on Apple
Silicon, so the experimental escape hatch comes off: the arm64 + 8.6 leg
fails the workflow like every other leg again. Docs record the bug as
fixed instead of as a platform exception.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U4cKi87mVQ896uSrw592fG

Copy link
Copy Markdown
Owner Author

Cleanup verification on ec393d2: 12 of 13 legs are green. The one red leg — Tests (PHP 8.6, macos-15-intel) — is not a zdebug regression:

No code change needed here. The leg will go green once setup-php ships an intel 8.6 nightly built from PHP-8.6 at or after Oct 9; I'll re-run it then. Upside: that run will be the first real binary validation of the upstream fix under an actually-selected TAILCALL VM.


Generated by Claude Code

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