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)
+
+ {closure}>
+
+
+
+
+
\ 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)
+
+
+
+
+
+
+
+
+
+
+
+
+{closure}>
+
+
+
\ 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
+
+ {closure}>
+
+
+
+
+
\ No newline at end of file