diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eebec5..3661281 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Comprehensive test coverage for all fiber scenarios - **TrueAsync API**: Added `ZEND_ASYNC_SCHEDULER_LAUNCH()` macro for scheduler initialization - **TrueAsync API**: Updated to version 0.8.0 with fiber support +- **TrueAsync API**: Added customizable scheduler heartbeat handler mechanism with `zend_async_set_heartbeat_handler()` API ### Fixed - **Critical GC Bug**: Fixed garbage collection crash during coroutine cancellation when exception occurs in main coroutine while GC is running diff --git a/scheduler.c b/scheduler.c index caaeb86..0aea33c 100644 --- a/scheduler.c +++ b/scheduler.c @@ -1125,6 +1125,8 @@ static zend_always_inline void scheduler_next_tick(void) zend_object **exception_ptr = &EG(exception); zend_object **prev_exception_ptr = &EG(prev_exception); + ZEND_ASYNC_SCHEDULER_HEARTBEAT; + execute_microtasks(); TRY_HANDLE_SUSPEND_EXCEPTION(); @@ -1195,8 +1197,6 @@ bool async_scheduler_coroutine_suspend(void) } } - ZEND_ASYNC_SCHEDULER_HEARTBEAT; - zend_coroutine_t *coroutine = ZEND_ASYNC_CURRENT_COROUTINE; // @@ -1330,6 +1330,7 @@ ZEND_STACK_ALIGNED void fiber_entry(zend_fiber_transfer *transfer) // Allocate VM stack on C stack instead of heap char vm_stack_memory[ZEND_FIBER_VM_STACK_SIZE]; bool *in_scheduler_context = &ZEND_ASYNC_SCHEDULER_CONTEXT; + zend_async_heartbeat_handler_t *heartbeat_handler = &ZEND_ASYNC_G(heartbeat_handler); zend_first_try { @@ -1380,10 +1381,13 @@ ZEND_STACK_ALIGNED void fiber_entry(zend_fiber_transfer *transfer) TRY_HANDLE_EXCEPTION(); - ZEND_ASYNC_SCHEDULER_HEARTBEAT; - *in_scheduler_context = true; + //ZEND_ASYNC_SCHEDULER_HEARTBEAT; + if (*heartbeat_handler) { + (*heartbeat_handler)(); + } + ZEND_ASSERT(circular_buffer_is_not_empty(resumed_coroutines) == 0 && "resumed_coroutines should be 0"); execute_microtasks(); diff --git a/tests/curl/005-error_handling.phpt b/tests/curl/005-error_handling.phpt index ddf8a6a..052d625 100644 --- a/tests/curl/005-error_handling.phpt +++ b/tests/curl/005-error_handling.phpt @@ -81,7 +81,7 @@ $coroutines = [ spawn(fn() => test_not_found($server)), ]; -$results = await_all($coroutines); +[$results, $exceptions] = await_all($coroutines); // Merge all outputs and sort by key to ensure deterministic order $all_output = []; @@ -102,14 +102,14 @@ async_test_server_stop($server); --EXPECTF-- Test start Testing connection error -Testing server error -Testing 404 error Connection failed as expected Error present: yes Error number: %d +Testing server error HTTP Code: 500 Error: none Response length: %d +Testing 404 error HTTP Code: 404 Response length: %d Test end \ No newline at end of file