Skip to content

Releases: true-async/php-src

PHP 8.6.0 TrueAsync 0.6.7

14 Apr 14:12

Choose a tag to compare

TrueAsync PHP 0.6.7 (php 8.6)

Highlights

  • FrankenPHP on Windows — both Release and Debug builds of FrankenPHP are now produced and shipped alongside the regular PHP artifacts.
  • Installer: optional FrankenPHP install — the Windows PowerShell installer now asks (or reads INSTALL_FRANKENPHP=true) whether to also install FrankenPHP next to php.exe.

Async extension

Added

  • PDO Pool: getAttribute() support for pool attributes. $pdo->getAttribute(PDO::ATTR_POOL_ENABLED) now returns true/false depending on whether the connection pool is active. PDO::ATTR_POOL_MIN and PDO::ATTR_POOL_MAX return the configured pool size limits (or false when pooling is disabled). PDO::ATTR_POOL_HEALTHCHECK_INTERVAL is a construction-only attribute and raises an error if read at runtime.

Fixed

  • Heap-use-after-free in await_all() / await_*() with string keys. When any await_* function received an array with non-interned string keys (e.g. from json_decode() or str_repeat()), the returned results/errors arrays had incorrect refcount on those keys. Root cause: async_waiting_callback_dispose was called twice per callback (once from zend_async_callbacks_remove during del_callback, once from ZEND_ASYNC_EVENT_CALLBACK_RELEASE), but did not check ref_count — it unconditionally called zval_ptr_dtor on the key each time, decrementing the string refcount twice instead of once. When the calling function's local variables were freed (i_free_compiled_variables), the already-freed string was accessed again. Fixed by adding a ref_count guard to async_waiting_callback_dispose: when ref_count > 1, decrement and return without touching resources; cleanup happens only on the final dispose (ref_count == 1).

Windows build

Added

  • FrankenPHP support for Windows (Release and Debug). Both build types now produce a slim *-frankenphp.zip addon archive containing only FrankenPHP-specific files: frankenphp.exe, libwatcher-c.dll, brotli*.dll and pthreadVC3.dll. The PHP runtime DLL and extensions are not duplicated — extract this archive on top of the main PHP package.
  • Debug FrankenPHP linkage. FrankenPHP's cgo configuration was split into cgo_windows.go / cgo_windows_debug.go gated by the zend_debug Go build tag. When building against a debug devel pack, the workflow passes -tags zend_debug so clang sees -DZEND_DEBUG=1, matching the signatures of _emalloc/_efree/_estrdup in php8ts_debug.lib (which gain ZEND_FILE_LINE_DC arguments in debug mode).
  • Installer: optional FrankenPHP install. installer/install.ps1 now exposes an INSTALL_FRANKENPHP environment variable and an interactive "Install FrankenPHP?" prompt. When enabled, the installer downloads the matching slim frankenphp addon archive (respecting the Release/Debug choice), verifies its checksum against the same sha256sums.txt, and extracts it on top of the main install — frankenphp.exe lands next to php.exe.

Fixed

  • Clang/MSVC ABI mismatch in frankenphp_extension.c. Calls to emalloc(sizeof(zval)) were routed through zend_alloc.h's __builtin_constant_p specialization to _emalloc_16, which MSVC-built php8ts.lib does not export. Replaced with safe_emalloc(1, sizeof(zval), 0) to hit the exported _safe_emalloc entry point.
  • strtok_r unresolved on Windows. The Windows CRT has no strtok_r. Replaced all four call sites in frankenphp_extension.c with php_strtok_r (portable wrapper from main/php_reentrancy.h).
  • Debug packaging hardcoded release DLL names. The Package FrankenPHP step tried to copy php8ts.dll, but debug builds ship php8ts_debug.dll (see win32/build/confutils.js PHPLIB). Packaging now globs php*ts*.dll and php*ts*.lib so both release and debug names work.

Installation

Windows (PowerShell)

irm https://raw.githubusercontent.com/true-async/releases/master/installer/install.ps1 | iex

To also install FrankenPHP non-interactively:

$env:INSTALL_FRANKENPHP="true"; irm https://raw.githubusercontent.com/true-async/releases/master/installer/install.ps1 | iex

Docker

docker pull trueasync/php-true-async:0.6.7-php8.6
docker pull trueasync/php-true-async:latest

PHP 8.6.0 TrueAsync 0.6.2

24 Mar 14:00

Choose a tag to compare

What's Changed

Zend Async API

  • zend_async_new_task_t factory: New API function type for creating thread pool tasks, registered through the reactor.
  • void *data field on zend_async_task_t: Generic user data pointer for passing context to thread pool task callbacks.
  • ZEND_ASYNC_NEW_TASK() / ZEND_ASYNC_NEW_TASK_EX() macros: Convenience macros for task creation.
  • zend_async_thread_pool_is_enabled(): Check if thread pool is available.

Streams

  • Non-blocking flock(): Inside coroutines, blocking lock operations (LOCK_SH, LOCK_EX) are offloaded to the libuv thread pool, allowing other coroutines to continue executing while waiting for a file lock.

Full Changelog: php-8.6.0-trueasync-0.6.1...php-8.6.0-trueasync-0.6.2

PHP 8.6.0 TrueAsync 0.6.0 — 2026-03-14

13 Mar 21:07

Choose a tag to compare

PHP 8.6.0 with TrueAsync 0.6.0 support. This release includes the following changes to the PHP core (Zend engine, streams, and async API).

Added

  • \Cancellation root class: New PHP core root class implementing \Throwable (alongside \Exception and \Error), added per the True Async RFC. Prevents cancellation exceptions from being accidentally caught by catch(\Exception) or catch(\Error) blocks.
  • Acting coroutine for error context (zend_async_globals_t.acting_coroutine): When set, zend_get_executed_filename_ex(), zend_get_executed_lineno(), and get_active_function_name() in Zend/zend_execute_API.c fall back to the coroutine's suspended execute_data for file, line, and function name. Zero-cost: only read when an error actually occurs.
  • Async File and Pipe I/O: Non-blocking I/O for plain files and pipes via php_stdiop_read/php_stdiop_write async path. Supported functions: fread, fwrite, fseek, ftell, rewind, fgets, fgetc, fgetcsv, fputcsv, ftruncate, fflush, fscanf, file_get_contents, file_put_contents, file(), copy, tmpfile, readfile, fpassthru, stream_get_contents, stream_copy_to_stream.
  • Pipe/Stream Read Timeout: stream_set_timeout() now works for pipe streams (proc_open pipes, TTY). In async mode, timeout is enforced via waker timer competing with IO event — whoever fires first wins. stream_get_meta_data()['timed_out'] correctly reports timeout state.
  • Async IO Seek API: ZEND_ASYNC_IO_SEEK for syncing libuv file offset after fseek/rewind.
  • Async IO Append Flag: ZEND_ASYNC_IO_APPEND flag for correct append-mode file offset initialization.

Fixed

  • Generator segfault in fiber-coroutine mode: Generators inside fiber coroutines were not marked with ZEND_GENERATOR_IN_FIBER because EG(active_fiber) is not set in coroutine mode. This caused shutdown destructors to close generators while the coroutine was still suspended, leading to a NULL execute_data dereference in zend_generator_resume. Fixed by also checking ZEND_ASYNC_CURRENT_COROUTINE with ZEND_COROUTINE_IS_FIBER.
  • stream_select() ignoring PHP-buffered data in async context: When fgets()/fread() pulled more data into PHP's internal stream buffer than returned, a subsequent stream_select() would not detect the buffered data because the async path only checks OS-level file descriptors. Fixed by checking stream_array_emulate_read_fd_set() before entering the async poll path. Resolved hangs in run-tests.php -j parallel workers on macOS.
  • Async file IO position tracking: Replaced bare lseek/_lseeki64 with zend_lseek across the reactor. Fixed append-mode offset init and fseek behavior. On Windows, append writes now query real EOF via lseek(SEEK_END) before dispatch to avoid stale cached offsets.

PHP 8.6.0 TrueAsync alpha.1

21 Feb 14:24

Choose a tag to compare

Pre-release

PHP 8.6.0 TrueAsync alpha.1

First alpha release of TrueAsync PHP 8.6.0.

This is a pre-release intended for testing. Do not use in production.


Changed

  • New \Cancellation root class — added to PHP core per the True Async RFC. Implements \Throwable alongside \Exception and \Error. Async\AsyncCancellation now extends \Cancellation instead of \Error, preventing cancellation exceptions from being accidentally caught by catch(\Exception) or catch(\Error) blocks.
    • Migration: Replace catch(Async\CancellationError $e) with catch(Async\AsyncCancellation $e) or catch(\Cancellation $e).

Fixed

  • stream_select() ignoring PHP-buffered data in async context — when fgets()/fread() pulled more data into PHP's internal buffer than returned, a subsequent stream_select() did not detect buffered data because the async path only checks OS-level file descriptors. Caused hangs in run-tests.php -j parallel workers on macOS. Fixed by checking stream_array_emulate_read_fd_set() before entering the async poll path.
  • Waker events not cleaned when coroutine is resumed outside scheduler context — stale event references could accumulate when a coroutine was resumed directly. Now ZEND_ASYNC_WAKER_CLEAN_EVENTS is called on resume outside the scheduler.

Related repositories

True Async 0.2.1 PHP Core

30 Jun 20:23
bbc465e

Choose a tag to compare

  • Compiler warnings for G++ version 11 and above have been fixed.
  • A configuration error has also been corrected.

True Async 0.2.0 PHP Core

30 Jun 12:11
bbc465e

Choose a tag to compare