Repository navigation
Conversation
Pin the git-built extensions (memcached, memcache, xdebug, phpredis) to commits. On 8.6, build apcu/ast from git, apply the unmerged memcache 8.6 PRs, patch rdkafka 6.0.5 and sqlsrv 5.13.3, and pin mongodb and parallel. Stop loading opcache.so for apache on 8.5+, where opcache is built in.
BOOKWORM_NEXT_VERSION is temporarily set back to 11, since all consumers use the _bookworm-11 tags and no bookworm-12 base exists. Set it back to 12 before merging.
Official PHP 8.6 Windows builds use vs18, so extensions must be built with it too. VS 2026 doesn't offer the 10.0.19041 SDK; use 10.0.26100.
The bookworm images build with clang, where the removed zval_dtor() and EMPTY_SWITCH_DEFAULT_CASE() are hard errors. Also run the new 8.6 build steps as separate commands so set -e catches failures instead of silently skipping the extension.
- Add 8.6 (API 20260924) to the generator version list, plus TEST_INTEGRATIONS_86/TEST_WEB_86 and the 8.6 xfail list (copied from 8.5). - Windows ZTS test_c and profiler arm64 jobs now run the two newest versions, so 8.5 keeps its coverage. - PHP lint, Configuration Consistency and the sidecar uid verify job stay on the newest GA release ($latest_ga_minor_major, 8.5 until 8.6 GA). - $windows_max_version switch (default 8.6) gates Windows jobs and tells the Windows packaging job the newest API to bundle. - $sury_max_version gate keeps 8.6 out of "verify debian": Sury only ships 8.6.0~beta3, whose API predates 20260924. - verify alpine uses php:8.6-rc-fpm-alpine until GA. - run-tests.php is parallel by default on 8.6: pass -j1 where tests ran serially (profiler phpt, x-profiling phpt, loader). - Root docker-compose and prof_asan GitHub workflow get 8.6.
- Add 20260924 to the final-artifact, SSI and debug-artifact API lists. - Skip Windows APIs above WINDOWS_MAX_PHP_API so the bundle does not fail when Windows 8.6 is switched off. - package.xml max 8.6.99, datadog-setup.php supports 8.6. - verify_packages: no php8.6-opcache on Debian (built in since 8.5); php86 binaries and /etc/php86 on Alpine.
- XtOffsetOf was removed: use offsetof. - ZEND_RESULT_CODE was removed: use zend_result (auto_flush.h now includes ext/compatibility.h for the PHP 7 typedef). - php_hash_bin2hex was removed: use zend_bin2hex on 8.6. - PG(error_log) is a zend_string* on 8.6. - zend_ini_string() returns const char* on 8.6 (hard error in C++ tests). Co-authored-by: Bob Weinand <bob.weinand@datadoghq.com>
Raise MAX_API_VERSION to 420260924 and MAX_PHP_VERSION to 8.6. _php_error_log() takes zend_string* arguments since PHP 8.6. The loader is built once (against 8.3), so with DD_TRACE_DEBUG=1 on 8.6 it passed a char buffer as a zend_string and logged garbage (out-of-bounds read). Dispatch on the runtime module API number, which is now recorded before the first log line.
❌ ErrorsYour PR has failed checks. Please review the issues below and take necessary action before merging. 🚦 62 Pipeline jobs failed
|
…uilds Split the >= 8.5 git extension builds (memcached, memcache, xdebug, phpredis) into one command per step so set -e stops on failures. Apply the memcache PR #120 + #122 delta from a committed patch instead of fetching unmerged PR commits by SHA. Check the sha256 of the patched rdkafka/sqlsrv tarballs and fail if the sed patches left a site unpatched.
Restore BOOKWORM_NEXT_VERSION=12 and point just the php-8.6 service (tag and base image) at BOOKWORM_CURRENT_VERSION, so the other ci-images Bookworm entries keep their -12 tags and nothing needs reverting.
Start-BitsTransfer probes with HEAD, which the GitHub releases mirror (added in #4265) rejects with 405, so every Windows CI image build failed before reaching docker build. GET on the same URL returns 200 and the expected sha256.
…-n for the -j probe Also drop the unused leaked ABI_NO variable from the link tracing extension jobs.
- ZEND_RESULT_CODE was removed: use int, like dd_appsec_rshutdown(). - zval_dtor was removed: use zval_ptr_dtor_nogc. - ZEND_LTOA was removed: format with ZEND_LONG_FMT. - php_verror lost its params argument. - php_hash_bin2hex was removed: use zend_bin2hex on 8.6. - Drop the 8.5 prerelease skip from module_order_opcache.phpt.
- Gradle matrix and images for 8.6.0RC2; the RC tarball URL comes from images.gradle (PHP_TARBALL_URL build arg). - build_dev_php.sh: fix the 85000 typo so 8.5+ use the built-in opcache, and build Xdebug from the same master pin as the bookworm CI image on 8.6. - Add test8.6-release and test8.6-release-zts jobs. The 8.6 image digests still need to be pushed and added to tag_mappings.gradle.
ZEND_INTERNAL_FUNCTION is now a zend_function_type enumerator, so re-export it under a php_function_type_enum cfg. The ZTS executor_globals_offset is negative on 8.6 (EG lives before the TSRM cache), so apply it with byte_offset instead of byte_add.
OPcache is compiled into PHP 8.5+ and its zend_extension has no handle, so ddog_php_jit_enabled() always returned false. Skip the handle check and resolve symbols through RTLD_DEFAULT, like the tracer fix in #4226.
- phpinfo blames JIT for disabled allocation profiling only on PHP versions where JIT actually disables it (also fixes 8.4.7+ and patched 8.1/8.2). - jit_04/jit_05 assert `true`/`false` with JIT on PHP 8.5+, skip without JIT. - post-install.sh selects ddtrace-<api>-alpine-zts.so on ZTS Alpine instead of the glibc ZTS build (official php:8.6 Alpine images are ZTS).
php-src #22487 replaced the scanner errloc and the parser location with line_start/line before 8.6.0RC2, so the persistent decode overrides wrote to the wrong method slots and every 8.6 MINIT crashed.
PHP 8.6 stores zend_ini_entry->def and ini_get_all(..., true) reads it, so registering the defs from a stack array left a dangling pointer.
The 8.6 appsec and profiler compile jobs pushed package loader to 52 needs, above GitLab's limit of 50, so the package child pipeline was never created.
PHP 8.6's TAILCALL VM tail-calls ZEND_VM_LEAVE/ZEND_VM_ENTER_EX instead of returning to execute_ex (php-src a135ac7736). The generator trampoline's call handler returned a plain opline, so execute_ex ran the post-op ZEND_RETURN on its stale execute_data (the userland caller), losing the generator and never firing the end hook. Set ZEND_VM_ENTER_BIT so execute_data is reloaded. username_success_tab_newline.phpt dumps object ids, so the language test runner turns it into EXPECTF, where %0A/%0D/%09 match NUL bytes (same as the already-xfailed *_null_byte.phpt tests).
| static const zend_op *ZEND_OPCODE_HANDLER_CCONV zai_interceptor_handle_created_generator_call(void) { | ||
| zai_interceptor_handle_created_generator_func(); | ||
| // Since 8.6 the TAILCALL VM's ZEND_VM_LEAVE no longer returns to execute_ex, whose execute_data may be stale: set ZEND_VM_ENTER_BIT to reload it. | ||
| return (const zend_op *)((uintptr_t)&zai_interceptor_generator_post_op[2] | 1 /* ZEND_VM_ENTER_BIT */); |
There was a problem hiding this comment.
Returning ZEND_VM_ENTER_BIT when the call vm is executed will actually give you an off-by-one jump into the function. Care has to be taken to only do this when the tail call vm is actually used.
| #if PHP_VERSION_ID >= 80600 | ||
| zend_bin2hex(exception_hash, (const unsigned char *)&exception_long_hash, sizeof(exception_long_hash)); | ||
| #else | ||
| php_hash_bin2hex(exception_hash, (unsigned char *)&exception_long_hash, sizeof(exception_long_hash)); |
There was a problem hiding this comment.
Please #define php_hash_bin2hex zend_bin2hex in compatibility.h instead.
Benchmarks [ appsec ]Benchmark execution time: 2026-10-07 13:15:17 Comparing candidate commit 83a8b71 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 12 metrics, 0 unstable metrics.
|
| // Oldest and two newest supported Windows targets, kept in sync automatically. | ||
| windows_test_c_job("windows test_c: zts", "zts", array_values(array_unique(array_merge( | ||
| [reset($windows_minor_major_targets)], | ||
| array_slice($windows_minor_major_targets, -2) | ||
| )))); |
| // across PHP versions (both LP64), so we only run the newest version. | ||
| $arm64_latest = [end($profiler_minor_major_targets)]; | ||
| // across PHP versions (both LP64), so we only run the two newest versions. | ||
| $arm64_latest = array_slice($profiler_minor_major_targets, -2); |
| // Newest PHP with Windows support. PHP 8.6 needs the vs18 (VS 2026) toolchain; | ||
| // set this to "8.5" if that cannot run on our Windows runners (no 8.6 Windows artifact ships then). | ||
| $windows_max_version = "8.6"; | ||
| $windows_minor_major_targets = array_values(array_filter($all_minor_major_targets, function($v) use ($windows_max_version) { return version_compare($v, "7.2", ">=") && version_compare($v, $windows_max_version, "<="); })); |
Benchmarks [ tracer ]Benchmark execution time: 2026-10-07 13:58:23 Comparing candidate commit 83a8b71 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 192 metrics, 2 unstable metrics.
|
…rix tweaks - interceptor: on 8.6 only the TAILCALL VM gets ZEND_VM_ENTER_BIT, via a separate handler picked at runtime with zend_vm_kind(); CALL returns &post_op[2] like 8.5. - Alias php_hash_bin2hex to zend_bin2hex in compatibility.h (tracer, appsec) instead of inline #if at the call sites. - Windows ZTS back to oldest + newest, profiler arm64 back to newest only. - Drop the $windows_max_version switch and WINDOWS_MAX_PHP_API.
zai_hook_safe_finish moves rsp onto a malloc'd stack. Valgrind only treats an SP change as a stack switch if it lands in another registered stack or moves more than --max-stackframe (2MB). Otherwise it handles it as a normal stack adjustment and marks the memory in between as noaccess/undefined. That is how the 8.6 valgrind job flagged fibers/fiber_observer_bailout.phpt: invalid writes in zai_hook_safe_finish, then uninitialised reads up to zend_fiber_destroy_context. Register both sides of the switch. Verified locally with --max-stackframe=4G to force the near-stack layout: 327 errors before, 0 after.
PHP 8.6 caches static closures that have no bound variables in the declaring function's runtime cache until the request ends (ZEND_DECLARE_LAMBDA_FUNCTION, EG(lambda_cache)). The WeakReference therefore stays alive even on vanilla PHP without ddtrace. Use a non-static closure so the test checks trace() again.
PHP 8.6 asserts get_property_ptr_ptr is never called with BP_VAR_IS. BP_VAR_W takes the same path IS did before (no undefined-property warning, unlike RW).
8.6 converts internal arg_info to zend_arg_info with a zend_string name, so reading it as zend_internal_arg_info gave garbage names and the wrong stride.
- run-tests: print termsig for signaled tests (8.6 spawns without a shell) - silence 8.6 return-in-finally deprecation and hexdec overflow notice in phpts - guzzle web fixture: avoid the deprecated Is class name in the JSON response - xfail new 8.6 language tests affected by injected headers / object handles - drop frankenphp and cakephp_latest from 8.6 until upstream supports it
…filter_register tests Without the 8.6 shell wrapper, stdout EOF often arrives before the process has exited, so proc_get_status() reports running and the signal is lost.
| #if PHP_VERSION_ID >= 80600 | ||
| # define php_hash_bin2hex zend_bin2hex | ||
| #endif |
There was a problem hiding this comment.
we usually do it the other way around. Change to use the modern name, then alias the modern name to the old one in compatibility.h
There was a problem hiding this comment.
You're right, that was me confusing the old and new named when I suggested that before. (and he then did >= 80600 :-D)
| if [[ -n ${PHP_TARBALL_URL:-} ]]; then | ||
| download_url=$PHP_TARBALL_URL | ||
| elif [[ $version_id -lt 50400 ]]; then |
There was a problem hiding this comment.
instead of this indirection via images.gradle, just put the url directly here, like is done for museum.php.net
No description provided.