diff --git a/Zend/zend_fibers.h b/Zend/zend_fibers.h index 39dc0916deb..aefe2e53be6 100644 --- a/Zend/zend_fibers.h +++ b/Zend/zend_fibers.h @@ -88,6 +88,9 @@ struct _zend_fiber_context { /* Fiber status. */ zend_fiber_status status; + /* Observer state */ + zend_execute_data *top_observed_frame; + /* Reserved for extensions */ void *reserved[ZEND_MAX_RESERVED_RESOURCES]; }; diff --git a/Zend/zend_observer.c b/Zend/zend_observer.c index aefa1bd02b3..c70844a7762 100644 --- a/Zend/zend_observer.c +++ b/Zend/zend_observer.c @@ -39,7 +39,6 @@ zend_llist zend_observer_fiber_destroy; int zend_observer_fcall_op_array_extension; -ZEND_TLS zend_execute_data *first_observed_frame; ZEND_TLS zend_execute_data *current_observed_frame; // Call during minit/startup ONLY @@ -95,7 +94,6 @@ ZEND_API void zend_observer_post_startup(void) ZEND_API void zend_observer_activate(void) { - first_observed_frame = NULL; current_observed_frame = NULL; } @@ -321,6 +319,8 @@ ZEND_API void ZEND_FASTCALL zend_observer_fiber_init_notify(zend_fiber_context * zend_llist_element *element; zend_observer_fiber_init_handler callback; + initializing->top_observed_frame = NULL; + for (element = zend_observer_fiber_init.head; element; element = element->next) { callback = *(zend_observer_fiber_init_handler *) element->data; callback(initializing); @@ -332,10 +332,17 @@ ZEND_API void ZEND_FASTCALL zend_observer_fiber_switch_notify(zend_fiber_context zend_llist_element *element; zend_observer_fiber_switch_handler callback; + if (from->status == ZEND_FIBER_STATUS_DEAD) { + zend_observer_fcall_end_all(); // fiber is either finished (call will do nothing) or has bailed out + } + for (element = zend_observer_fiber_switch.head; element; element = element->next) { callback = *(zend_observer_fiber_switch_handler *) element->data; callback(from, to); } + + from->top_observed_frame = current_observed_frame; + current_observed_frame = to->top_observed_frame; } ZEND_API void ZEND_FASTCALL zend_observer_fiber_destroy_notify(zend_fiber_context *destroying) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index ca60fd82fcd..9852887ef74 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -756,6 +756,7 @@ PHP_MSHUTDOWN_FUNCTION(zend_test) PHP_RINIT_FUNCTION(zend_test) { zend_hash_init(&ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0); + ZT_G(observer_nesting_depth) = 0; return SUCCESS; } diff --git a/ext/zend_test/tests/observer_fiber_functions_01.phpt b/ext/zend_test/tests/observer_fiber_functions_01.phpt new file mode 100644 index 00000000000..d3d395bd302 --- /dev/null +++ b/ext/zend_test/tests/observer_fiber_functions_01.phpt @@ -0,0 +1,59 @@ +--TEST-- +Observer: Basic function observing in fibers +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.fiber_init=1 +zend_test.observer.fiber_switch=1 +zend_test.observer.fiber_destroy=1 +--FILE-- +start(); +$fiber->resume(); + +?> +--EXPECTF-- + + + + + + + + + + + + <{closure}> + + +int(1) + + + + + + + + + + + + +int(2) + + + + + + + \ No newline at end of file diff --git a/ext/zend_test/tests/observer_fiber_functions_02.phpt b/ext/zend_test/tests/observer_fiber_functions_02.phpt new file mode 100644 index 00000000000..c2b7eb007fa --- /dev/null +++ b/ext/zend_test/tests/observer_fiber_functions_02.phpt @@ -0,0 +1,54 @@ +--TEST-- +Observer: Function observing in fibers with unfinished fiber +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.fiber_init=1 +zend_test.observer.fiber_switch=1 +zend_test.observer.fiber_destroy=1 +--FILE-- +start(); + +?> +--EXPECTF-- + + + + + + + + + + + + <{closure}> + + +int(1) + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ext/zend_test/tests/observer_fiber_functions_03.phpt b/ext/zend_test/tests/observer_fiber_functions_03.phpt new file mode 100644 index 00000000000..d96390068a2 --- /dev/null +++ b/ext/zend_test/tests/observer_fiber_functions_03.phpt @@ -0,0 +1,84 @@ +--TEST-- +Observer: Function observing in fibers with bailout in fiber +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.fiber_init=1 +zend_test.observer.fiber_switch=1 +zend_test.observer.fiber_destroy=1 +memory_limit=100M +--FILE-- +start(); + +$fiber = new Fiber(function (): void { + var_dump(2); + Fiber::suspend(); + str_repeat('A', 200_000_000); +}); + +$fiber->start(); +$fiber->resume(); + +?> +--EXPECTF-- + + + + + + + + + + + + <{closure}> + + +int(1) + + + + + + + + + + + + + + <{closure}> + +int(2) + + + + + + + + + + + + + +Fatal error: Allowed memory size of 104857600 bytes exhausted %s on line %d + + + + + + + \ No newline at end of file