Skip to content

merge: cascade 8.4 (ZTS support) into master + PHP 8.5 ZTS artifacts + CI docker caching - #145

Merged
lisachenko merged 12 commits into
masterfrom
claude/zts-support-ci-k2pc93
Aug 7, 2026
Merged

merge: cascade 8.4 (ZTS support) into master + PHP 8.5 ZTS artifacts + CI docker caching#145
lisachenko merged 12 commits into
masterfrom
claude/zts-support-ci-k2pc93

Conversation

@lisachenko

@lisachenko lisachenko commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Resolves the conflicted cascade PR #144 (its 8.4 head is contained in this branch, so merging this PR marks #144 merged as well), and completes the master side of the ZTS work from #143 / issue #60.

Cascade merge (conflict resolution)

Only 3 files conflicted; everything else auto-merged:

  • src/Core.php — kept master's PHP 8.5 pins (SUPPORTED_PHP_VERSION_ID = [80500, 80600], relocated ZEND_ACC_USE_GUARDS, 8.5 docblocks) plus the 8.4 branch's TSRM resolution (threadGlobals() / threadLocalStorageBase() + the ZTS branch in init()).
  • tools/generator/generate.php — targets resolved to 8.5-nts + 8.5-zts (master's docblock and CLI defaults kept).
  • README.md — both maintained rows now list linux-x64-nts, linux-x64-zts.

PHP 8.5 ZTS artifacts

  • include/8.5/linux-x64-zts/being generated right now under a release --enable-zts PHP 8.5.9 source build; lands as the next commit on this branch. Until then the ZTS CI legs and header-drift are expected red.
  • The mandatory byte-identity pre-check already passed on this branch's merged manifest: host regeneration of include/8.5/linux-x64-nts is byte-identical to master's committed artifacts (40 struct layouts validated), proving the host pipeline and the TS-conditional manifest are sound on 8.5.

CI docker-layer caching (requested)

Both docker-building jobs now cache image layers with first-party actions/cache:

  • tests-internal-debug builds through buildx with --cache-from/--cache-to type=local and a rotate step (bounded cache); a warm cache turns the multi-minute PHP source compile into a layer restore. Keyed on Dockerfile hash + PHP minor + TS mode.
  • header-drift: generate.php gains an opt-in Z_ENGINE_BUILDX_CACHE_DIR passthrough (per-target subdirectories, rotated in the script) so the generator's apt/clang/ext-ffi layers restore from cache while the emit stage — which produces the drift-checked artifacts — always re-runs.

The same caching commit can be cherry-picked to the 8.4 branch to keep future cascades conflict-free.

Validation (in progress, will update)

  • 8.5 NTS byte-identity pre-check (host pipeline vs committed artifacts)
  • Full default suite under local PHP 8.5.9 ZTS + test:opcache-zts gate + worker-loop soak + internal group
  • Full default suite under local PHP 8.5.9 NTS (regression), phpstan level max, cs

🤖 Generated with Claude Code

https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa


Generated by Claude Code

claude and others added 12 commits August 7, 2026 19:35
…zts target

On ZTS builds executor_globals/compiler_globals are not linkable symbols -
the engine exports the TSRM byte offsets instead (Zend/zend_globals.h), and
tsrm_get_ls_cache() is the exported accessor for the calling thread's
local-storage block. The manifest now selects the right symbol set for the
build emit.php runs under, and the generator maintains both 8.4 targets.

Part of #60

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
Generated with the documented Docker-free host pipeline (AGENTS.md) under a
release --enable-zts build of PHP 8.4.24, after the mandatory byte-identity
pre-check reproduced the committed NTS artifacts exactly (before and after
the manifest change - the committed NTS artifacts are untouched). The emit
pipeline's FFI validation stage verified all 39 struct layouts against the
C compiler under the ZTS interpreter.

Part of #60

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
Core::init() now resolves the per-thread executor/compiler globals exactly
like the engine's own EG()/CG() fast path: tsrm_get_ls_cache() plus the
engine-exported executor_globals_offset/compiler_globals_offset. The NTS
path is untouched and the public API is unchanged - Executor/Compiler
receive the same struct CData species as before.

Extracting the returned void* value needs care: a call-returned pointer
CData carries the target, not a slot, so the base is read through a typed
integer view of an addr() slot (the shape PayloadRelocator::ptrValue
already documents). Core::threadLocalStorageBase() exposes the resolved
base internally for the module-globals accessor.

The smoke test proves the resolved view is the live per-thread block: a
native error_reporting() write must be immediately visible through
Core::$executor.

Closes #60 (runtime part)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
zend_module_entry has no globals_ptr on ZTS - the entry carries a pointer
to a ts_rsrc_id slot that zend_startup_module_ex() hands to
ts_allocate_id(), and the TSRM allocates the per-thread globals itself.
AbstractModule::register() now fills globals_id_ptr on ZTS, and
ReflectionExtension::getGlobals() resolves the calling thread's block the
same way as ZEND_MODULE_GLOBALS_ACCESSOR (entry->storage[id - 1]).

Part of #60

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
ZTS payloads use a different binary layout, so PayloadRelocator now
refuses them explicitly instead of walking them wrong. The relocator
tests carry an opcache-relocator group and self-skip on ZTS; the new
test:opcache-zts script is the ZTS non-skip gate for the remaining
opcache/SHM coverage (issue #124 semantics preserved).

Part of #60, tracked in #118

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
Both the release tests job and the debug internal-group job now run a
NTS x ZTS matrix: setup-php provides the thread-safe build via phpts,
and the debug Dockerfile gains a PHP_TS build-arg that adds --enable-zts
to the source rebuild. The header-drift job covers the new zts target
automatically through the generator's default target list. The ZTS legs
gate opcache coverage with the relocator group excluded (#118).

NOTE: the debug job's required-check name now carries the matrix label
("Internal group (debug build, NTS)") - branch protection rules need
updating.

Part of #60

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
Part of #60

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
feat(core): Thread-safe (ZTS) runtime support + ZTS CI matrix
Conflict resolution: master's PHP 8.5 pins (SUPPORTED_PHP_VERSION_ID,
ZEND_ACC_USE_GUARDS, docblocks) + the 8.4 branch's TSRM/ZTS additions;
generator targets resolved to 8.5-nts + 8.5-zts; README matrix gains
linux-x64-zts on both maintained rows. The include/8.5/linux-x64-zts
artifacts are generated in a follow-up commit on this branch (per
AGENTS.md, headers are regenerated on the target branch, never merged
textually).

Resolves the cascade tracked by PR #144

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
The debug-build jobs recompile PHP from source on every run and the
header-drift job rebuilds the generator toolchain image; both now build
through buildx with a local layer cache wrapped in actions/cache. The
debug job rotates the cache directory to keep it bounded; generate.php
gains an opt-in Z_ENGINE_BUILDX_CACHE_DIR passthrough with per-target
subdirectories and the same rotation, so the emit stage still re-runs
(it produces the artifacts under drift check) while the apt/clang/ffi
layers restore from cache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
Generated with the documented Docker-free host pipeline under a release
--enable-zts build of PHP 8.5.9, after the byte-identity pre-check
reproduced master's committed 8.5 NTS artifacts exactly with the merged
thread-safety-aware manifest. The emit pipeline's FFI validation stage
verified all 40 struct layouts against the C compiler under the ZTS
interpreter; CI's header-drift job re-derives both 8.5 targets in Docker
and diffs against these files.

Completes the master side of #60 (see PR #143 / #144)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mWPLkDoKWoDDS9W9LSaDa
@lisachenko
lisachenko marked this pull request as ready for review August 7, 2026 20:20
@lisachenko
lisachenko merged commit eff112e into master Aug 7, 2026
7 checks passed
@lisachenko
lisachenko deleted the claude/zts-support-ci-k2pc93 branch August 7, 2026 20:21
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