@@ -334,31 +334,7 @@ static zend_always_inline zend_vm_stack zend_fiber_vm_stack_alloc(size_t size) /
334
334
}
335
335
/* }}} */
336
336
337
- static void zend_fiber_execute (zend_fiber * fiber ) /* {{{ */
338
- {
339
- fiber -> fci .retval = & fiber -> value ;
340
-
341
- zend_call_function (& fiber -> fci , & fiber -> fci_cache );
342
-
343
- if (EG (exception )) {
344
- if (fiber -> status == ZEND_FIBER_STATUS_SHUTDOWN ) {
345
- if (EXPECTED (zend_is_fiber_exit (EG (exception )))) {
346
- zend_clear_exception ();
347
- } else {
348
- zend_exception_error (EG (exception ), E_ERROR );
349
- }
350
- } else {
351
- fiber -> status = ZEND_FIBER_STATUS_THREW ;
352
- }
353
- } else {
354
- fiber -> status = ZEND_FIBER_STATUS_RETURNED ;
355
- }
356
-
357
- GC_DELREF (& fiber -> std );
358
- }
359
- /* }}} */
360
-
361
- static void zend_fiber_run (zend_fiber_context * context ) /* {{{ */
337
+ static void zend_fiber_execute (zend_fiber_context * context ) /* {{{ */
362
338
{
363
339
zend_fiber * fiber = EG (current_fiber );
364
340
ZEND_ASSERT (fiber );
@@ -382,10 +358,32 @@ static void zend_fiber_run(zend_fiber_context *context) /* {{{ */
382
358
EG (jit_trace_num ) = 0 ;
383
359
EG (error_reporting ) = error_reporting ;
384
360
385
- zend_fiber_execute (fiber );
361
+ fiber -> fci .retval = & fiber -> value ;
362
+
363
+ // Reference added while running, removed when suspended, and added again once resumed.
364
+ GC_ADDREF (& fiber -> std );
365
+
366
+ zend_call_function (& fiber -> fci , & fiber -> fci_cache );
367
+
368
+ if (EG (exception )) {
369
+ if (fiber -> status == ZEND_FIBER_STATUS_SHUTDOWN ) {
370
+ if (EXPECTED (zend_is_fiber_exit (EG (exception )))) {
371
+ zend_clear_exception ();
372
+ } else {
373
+ zend_exception_error (EG (exception ), E_ERROR );
374
+ }
375
+ } else {
376
+ fiber -> status = ZEND_FIBER_STATUS_THREW ;
377
+ }
378
+ } else {
379
+ fiber -> status = ZEND_FIBER_STATUS_RETURNED ;
380
+ }
386
381
387
382
zend_vm_stack_destroy ();
388
383
fiber -> execute_data = NULL ;
384
+
385
+ // Remove reference added at last resume.
386
+ GC_DELREF (& fiber -> std );
389
387
}
390
388
/* }}} */
391
389
@@ -474,15 +472,13 @@ ZEND_METHOD(Fiber, start)
474
472
fiber -> fci .params = ZEND_CALL_ARG (execute_data , 1 );
475
473
fiber -> fci .param_count = ZEND_CALL_NUM_ARGS (execute_data );
476
474
477
- if (!zend_fiber_init_context (& fiber -> context , zend_fiber_run , EG (fiber_stack_size ))) {
475
+ if (!zend_fiber_init_context (& fiber -> context , zend_fiber_execute , EG (fiber_stack_size ))) {
478
476
zend_throw_error (NULL , "Could not create fiber context" );
479
477
return ;
480
478
}
481
479
482
480
fiber -> status = ZEND_FIBER_STATUS_RUNNING ;
483
481
484
- GC_ADDREF (& fiber -> std );
485
-
486
482
zend_fiber_switch_to (fiber );
487
483
488
484
zval_ptr_dtor (& fiber -> fci .function_name );
@@ -530,6 +526,7 @@ ZEND_METHOD(Fiber, suspend)
530
526
fiber -> execute_data = execute_data ;
531
527
fiber -> status = ZEND_FIBER_STATUS_SUSPENDED ;
532
528
529
+ // Remove running reference while suspended.
533
530
GC_DELREF (& fiber -> std );
534
531
535
532
zend_fiber_suspend (fiber );
@@ -541,6 +538,7 @@ ZEND_METHOD(Fiber, suspend)
541
538
}
542
539
543
540
fiber -> status = ZEND_FIBER_STATUS_RUNNING ;
541
+ // Add reference while fiber is running.
544
542
GC_ADDREF (& fiber -> std );
545
543
546
544
if (!fiber -> error ) {
0 commit comments