Skip to content

Validate task functions before execution#387

Open
realFlowControl wants to merge 10 commits into
developfrom
florian/phase-2-link-functions
Open

Validate task functions before execution#387
realFlowControl wants to merge 10 commits into
developfrom
florian/phase-2-link-functions

Conversation

@realFlowControl

@realFlowControl realFlowControl commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

What and why

Tasks run in an isolated runtime and do not inherit user-defined functions from the thread that submits them. Calling one of those functions without loading it in the destination runtime previously allowed the task to start before failing with a generic undefined-function error, so users could see partial task side effects without guidance about the actual dependency mistake. This change validates statically named function dependencies before executing the task and reports an actionable parallel\Runtime\Error\IllegalInstruction through Future::value() instead.

The error identifies the missing function and explains the two supported ways to provide it: define it in the runtime bootstrap or pass a closure created with Closure::fromCallable() as a task argument. Because validation happens before execution, no task statement runs when a static dependency is missing.

Implementation

The scheduler performs the validation in the destination runtime immediately before zend_execute_ex(), where the destination function table is available. It scans ZEND_INIT_FCALL, ZEND_INIT_FCALL_BY_NAME, and ZEND_INIT_NS_FCALL_BY_NAME, including namespace fallback, and recursively validates functions referenced by ZEND_DECLARE_LAMBDA_FUNCTION so nested closures have the same behavior.

Each static call is resolved with zend_fetch_function(). Direct calls also verify that the destination definition has a compatible call-frame size and seed the task's runtime-cache slot with that definition. A validation failure is converted into the existing future error path with the task source file and line, and the execution frame is cleaned up without running the task.

Function names known only at runtime, such as $function(), cannot be checked ahead of execution. An include inside the task is too late to satisfy a static dependency because validation runs first. A same-name function already present in the destination runtime is accepted; definitions are not compared by source identity.

The README now documents this task dependency boundary and the existing undefined-function regressions assert the new pre-execution diagnostic. A dedicated nested-closure regression ensures OPcache and JIT cannot optimize away the dependency being tested.

Testing

  • PHP 8.4 full suite without OPcache: 148 passed.
  • Focused function-validation regressions pass locally without OPcache, with OPcache, and with function JIT.
  • ASAN, UBSAN, Linux, Windows, clang-format, and coverage checks pass across the supported PHP matrix.

@realFlowControl realFlowControl changed the title Link task functions in destination runtimes Validate task functions before execution Jul 14, 2026
@realFlowControl
realFlowControl force-pushed the florian/phase-2-link-functions branch from c388a1e to 7181cb3 Compare July 15, 2026 08:08
@realFlowControl
realFlowControl force-pushed the florian/phase-2-link-functions branch from e9640f9 to a2d5e9d Compare July 15, 2026 08:22
@realFlowControl realFlowControl self-assigned this Jul 15, 2026
@realFlowControl
realFlowControl marked this pull request as ready for review July 15, 2026 09:48
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.

1 participant