@@ -425,7 +425,9 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer)
425
425
426
426
zend_call_function (& fiber -> fci , & fiber -> fci_cache );
427
427
428
+ /* Cleanup callback and unset field to prevent GC / duplicate dtor issues. */
428
429
zval_ptr_dtor (& fiber -> fci .function_name );
430
+ ZVAL_UNDEF (& fiber -> fci .function_name );
429
431
430
432
if (EG (exception )) {
431
433
if (!(fiber -> flags & ZEND_FIBER_FLAG_DESTROYED )
@@ -516,9 +518,8 @@ static zend_always_inline zend_fiber_transfer zend_fiber_suspend(zend_fiber *fib
516
518
517
519
static zend_object * zend_fiber_object_create (zend_class_entry * ce )
518
520
{
519
- zend_fiber * fiber ;
521
+ zend_fiber * fiber = emalloc ( sizeof ( zend_fiber )) ;
520
522
521
- fiber = emalloc (sizeof (zend_fiber ));
522
523
memset (fiber , 0 , sizeof (zend_fiber ));
523
524
524
525
zend_object_std_init (& fiber -> std , ce );
@@ -565,16 +566,25 @@ static void zend_fiber_object_free(zend_object *object)
565
566
{
566
567
zend_fiber * fiber = (zend_fiber * ) object ;
567
568
568
- if (fiber -> context .status == ZEND_FIBER_STATUS_INIT ) {
569
- // Fiber was never started, so we need to release the reference to the callback.
570
- zval_ptr_dtor (& fiber -> fci .function_name );
571
- }
572
-
569
+ zval_ptr_dtor (& fiber -> fci .function_name );
573
570
zval_ptr_dtor (& fiber -> result );
574
571
575
572
zend_object_std_dtor (& fiber -> std );
576
573
}
577
574
575
+ static HashTable * zend_fiber_object_gc (zend_object * object , zval * * table , int * num )
576
+ {
577
+ zend_fiber * fiber = (zend_fiber * ) object ;
578
+ zend_get_gc_buffer * buf = zend_get_gc_buffer_create ();
579
+
580
+ zend_get_gc_buffer_add_zval (buf , & fiber -> fci .function_name );
581
+ zend_get_gc_buffer_add_zval (buf , & fiber -> result );
582
+
583
+ zend_get_gc_buffer_use (buf , table , num );
584
+
585
+ return NULL ;
586
+ }
587
+
578
588
ZEND_METHOD (Fiber , __construct )
579
589
{
580
590
zend_fiber * fiber = (zend_fiber * ) Z_OBJ_P (ZEND_THIS );
@@ -590,12 +600,9 @@ ZEND_METHOD(Fiber, __construct)
590
600
ZEND_METHOD (Fiber , start )
591
601
{
592
602
zend_fiber * fiber = (zend_fiber * ) Z_OBJ_P (ZEND_THIS );
593
- zval * params ;
594
- uint32_t param_count ;
595
- zend_array * named_params ;
596
603
597
604
ZEND_PARSE_PARAMETERS_START (0 , -1 )
598
- Z_PARAM_VARIADIC_WITH_NAMED (params , param_count , named_params );
605
+ Z_PARAM_VARIADIC_WITH_NAMED (fiber -> fci . params , fiber -> fci . param_count , fiber -> fci . named_params );
599
606
ZEND_PARSE_PARAMETERS_END ();
600
607
601
608
if (UNEXPECTED (zend_fiber_switch_blocked ())) {
@@ -608,10 +615,6 @@ ZEND_METHOD(Fiber, start)
608
615
RETURN_THROWS ();
609
616
}
610
617
611
- fiber -> fci .params = params ;
612
- fiber -> fci .param_count = param_count ;
613
- fiber -> fci .named_params = named_params ;
614
-
615
618
if (!zend_fiber_init_context (& fiber -> context , zend_ce_fiber , zend_fiber_execute , EG (fiber_stack_size ))) {
616
619
RETURN_THROWS ();
617
620
}
@@ -827,6 +830,7 @@ void zend_register_fiber_ce(void)
827
830
zend_fiber_handlers = std_object_handlers ;
828
831
zend_fiber_handlers .dtor_obj = zend_fiber_object_destroy ;
829
832
zend_fiber_handlers .free_obj = zend_fiber_object_free ;
833
+ zend_fiber_handlers .get_gc = zend_fiber_object_gc ;
830
834
zend_fiber_handlers .clone_obj = NULL ;
831
835
832
836
zend_ce_fiber_error = register_class_FiberError (zend_ce_error );
0 commit comments