Skip to content

Commit d2e5203

Browse files
trowskitwose
andauthored
Split fiber status and flags (#7094)
Co-Authored-By: twosee <twose@qq.com>
1 parent b601acf commit d2e5203

File tree

5 files changed

+51
-40
lines changed

5 files changed

+51
-40
lines changed

Zend/zend_fibers.c

+18-15
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ static void zend_fiber_switch_to(zend_fiber *fiber)
321321

322322
zend_observer_fiber_switch_notify(fiber, previous);
323323

324-
if (UNEXPECTED(fiber->status == ZEND_FIBER_STATUS_BAILOUT)) {
324+
if (UNEXPECTED(fiber->flags & ZEND_FIBER_FLAG_BAILOUT)) {
325325
// zend_bailout() was called in the fiber, so call it again in the previous fiber or {main}.
326326
zend_bailout();
327327
}
@@ -379,20 +379,20 @@ static void ZEND_STACK_ALIGNED zend_fiber_execute(zend_fiber_context *context)
379379
zval_ptr_dtor(&fiber->fci.function_name);
380380

381381
if (EG(exception)) {
382-
if (fiber->status == ZEND_FIBER_STATUS_SHUTDOWN) {
382+
if (fiber->flags & ZEND_FIBER_FLAG_DESTROYED) {
383383
if (EXPECTED(zend_is_graceful_exit(EG(exception)) || zend_is_unwind_exit(EG(exception)))) {
384384
zend_clear_exception();
385385
}
386386
} else {
387-
fiber->status = ZEND_FIBER_STATUS_THREW;
387+
fiber->flags = ZEND_FIBER_FLAG_THREW;
388388
}
389-
} else {
390-
fiber->status = ZEND_FIBER_STATUS_RETURNED;
391389
}
392390
} zend_catch {
393-
fiber->status = ZEND_FIBER_STATUS_BAILOUT;
391+
fiber->flags |= ZEND_FIBER_FLAG_BAILOUT;
394392
} zend_end_try();
395393

394+
fiber->status = ZEND_FIBER_STATUS_DEAD;
395+
396396
zend_vm_stack_destroy();
397397
fiber->execute_data = NULL;
398398
fiber->stack_bottom = NULL;
@@ -422,7 +422,8 @@ static void zend_fiber_object_destroy(zend_object *object)
422422
zend_object *exception = EG(exception);
423423
EG(exception) = NULL;
424424

425-
fiber->status = ZEND_FIBER_STATUS_SHUTDOWN;
425+
fiber->status = ZEND_FIBER_STATUS_RUNNING;
426+
fiber->flags |= ZEND_FIBER_FLAG_DESTROYED;
426427

427428
zend_fiber_switch_to(fiber);
428429

@@ -499,7 +500,7 @@ ZEND_API void zend_fiber_start(zend_fiber *fiber, zval *params, uint32_t param_c
499500

500501
zend_fiber_switch_to(fiber);
501502

502-
if (fiber->status & ZEND_FIBER_STATUS_FINISHED) {
503+
if (fiber->status == ZEND_FIBER_STATUS_DEAD) {
503504
RETURN_NULL();
504505
}
505506

@@ -530,7 +531,7 @@ ZEND_API void zend_fiber_suspend(zval *value, zval *return_value)
530531
RETURN_THROWS();
531532
}
532533

533-
if (UNEXPECTED(fiber->status == ZEND_FIBER_STATUS_SHUTDOWN)) {
534+
if (UNEXPECTED(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)) {
534535
zend_throw_error(zend_ce_fiber_error, "Cannot suspend in a force-closed fiber");
535536
RETURN_THROWS();
536537
}
@@ -549,7 +550,7 @@ ZEND_API void zend_fiber_suspend(zval *value, zval *return_value)
549550

550551
zend_fiber_suspend_from(fiber);
551552

552-
if (fiber->status == ZEND_FIBER_STATUS_SHUTDOWN) {
553+
if (fiber->flags & ZEND_FIBER_FLAG_DESTROYED) {
553554
// This occurs when the fiber is GC'ed while suspended.
554555
zend_throw_graceful_exit();
555556
RETURN_THROWS();
@@ -599,7 +600,7 @@ ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_val
599600

600601
zend_fiber_switch_to(fiber);
601602

602-
if (fiber->status & ZEND_FIBER_STATUS_FINISHED) {
603+
if (fiber->status == ZEND_FIBER_STATUS_DEAD) {
603604
RETURN_NULL();
604605
}
605606

@@ -637,7 +638,7 @@ ZEND_API void zend_fiber_throw(zend_fiber *fiber, zval *exception, zval *return_
637638

638639
zend_fiber_switch_to(fiber);
639640

640-
if (fiber->status & ZEND_FIBER_STATUS_FINISHED) {
641+
if (fiber->status == ZEND_FIBER_STATUS_DEAD) {
641642
RETURN_NULL();
642643
}
643644

@@ -700,7 +701,7 @@ ZEND_METHOD(Fiber, isTerminated)
700701

701702
fiber = (zend_fiber *) Z_OBJ_P(getThis());
702703

703-
RETURN_BOOL(fiber->status & ZEND_FIBER_STATUS_FINISHED);
704+
RETURN_BOOL(fiber->status == ZEND_FIBER_STATUS_DEAD);
704705
}
705706

706707
ZEND_METHOD(Fiber, getReturn)
@@ -711,13 +712,15 @@ ZEND_METHOD(Fiber, getReturn)
711712

712713
fiber = (zend_fiber *) Z_OBJ_P(getThis());
713714

714-
if (fiber->status != ZEND_FIBER_STATUS_RETURNED) {
715+
if (fiber->status != ZEND_FIBER_STATUS_DEAD || fiber->flags) {
715716
const char *message;
716717

717718
if (fiber->status == ZEND_FIBER_STATUS_INIT) {
718719
message = "The fiber has not been started";
719-
} else if (fiber->status == ZEND_FIBER_STATUS_THREW) {
720+
} else if (fiber->flags & ZEND_FIBER_FLAG_THREW) {
720721
message = "The fiber threw an exception";
722+
} else if (fiber->flags & ZEND_FIBER_FLAG_BAILOUT) {
723+
message = "The fiber exited with a fatal error";
721724
} else {
722725
message = "The fiber has not returned";
723726
}

Zend/zend_fibers.h

+18-12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@
2525

2626
BEGIN_EXTERN_C()
2727

28+
typedef enum {
29+
ZEND_FIBER_STATUS_INIT,
30+
ZEND_FIBER_STATUS_RUNNING,
31+
ZEND_FIBER_STATUS_SUSPENDED,
32+
ZEND_FIBER_STATUS_DEAD,
33+
} zend_fiber_status;
34+
35+
typedef enum {
36+
ZEND_FIBER_FLAG_THREW = 1 << 0,
37+
ZEND_FIBER_FLAG_BAILOUT = 1 << 1,
38+
ZEND_FIBER_FLAG_DESTROYED = 1 << 2,
39+
} zend_fiber_flag;
40+
2841
void zend_register_fiber_ce(void);
2942
void zend_fiber_init(void);
3043

@@ -59,8 +72,11 @@ typedef struct _zend_fiber {
5972
/* Fiber PHP object handle. */
6073
zend_object std;
6174

62-
/* Status of the fiber, one of the ZEND_FIBER_STATUS_* constants. */
63-
zend_uchar status;
75+
/* Status of the fiber, one of the zend_fiber_status values. */
76+
zend_fiber_status status;
77+
78+
/* Flags of the fiber, bit field of the zend_fiber_flag values. */
79+
zend_uchar flags;
6480

6581
/* Callback and info / cache to be used when fiber is started. */
6682
zend_fcall_info fci;
@@ -82,16 +98,6 @@ typedef struct _zend_fiber {
8298
zval value;
8399
} zend_fiber;
84100

85-
static const zend_uchar ZEND_FIBER_STATUS_INIT = 0x0;
86-
static const zend_uchar ZEND_FIBER_STATUS_SUSPENDED = 0x1;
87-
static const zend_uchar ZEND_FIBER_STATUS_RUNNING = 0x2;
88-
static const zend_uchar ZEND_FIBER_STATUS_RETURNED = 0x4;
89-
static const zend_uchar ZEND_FIBER_STATUS_THREW = 0x8;
90-
static const zend_uchar ZEND_FIBER_STATUS_SHUTDOWN = 0x10;
91-
static const zend_uchar ZEND_FIBER_STATUS_BAILOUT = 0x20;
92-
93-
static const zend_uchar ZEND_FIBER_STATUS_FINISHED = 0x2c;
94-
95101
/* These functions create and manipulate a Fiber object, allowing any internal function to start, resume, or suspend a fiber. */
96102
ZEND_API zend_fiber *zend_fiber_create(const zend_fcall_info *fci, const zend_fcall_info_cache *fci_cache);
97103
ZEND_API void zend_fiber_start(zend_fiber *fiber, zval *params, uint32_t param_count, zend_array *named_params, zval *return_value);

ext/reflection/php_reflection.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -6873,7 +6873,7 @@ ZEND_METHOD(ReflectionFiber, getFiber)
68736873
}
68746874

68756875
#define REFLECTION_CHECK_VALID_FIBER(fiber) do { \
6876-
if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_INIT || fiber->status & ZEND_FIBER_STATUS_FINISHED) { \
6876+
if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_INIT || fiber->status == ZEND_FIBER_STATUS_DEAD) { \
68776877
zend_throw_error(NULL, "Cannot fetch information from a fiber that has not been started or is terminated"); \
68786878
RETURN_THROWS(); \
68796879
} \
@@ -6948,7 +6948,7 @@ ZEND_METHOD(ReflectionFiber, getCallable)
69486948

69496949
ZEND_PARSE_PARAMETERS_NONE();
69506950

6951-
if (fiber == NULL || fiber->status & ZEND_FIBER_STATUS_FINISHED) {
6951+
if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_DEAD) {
69526952
zend_throw_error(NULL, "Cannot fetch the callable from a fiber that has terminated"); \
69536953
RETURN_THROWS();
69546954
}

ext/zend_test/test.c

+13-9
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,11 @@ static void fiber_enter_observer(zend_fiber *from, zend_fiber *to)
425425
if (to->status == ZEND_FIBER_STATUS_INIT) {
426426
php_printf("<init '%p'>\n", to);
427427
} else if (to->status == ZEND_FIBER_STATUS_RUNNING && (!from || from->status == ZEND_FIBER_STATUS_RUNNING)) {
428-
php_printf("<resume '%p'>\n", to);
429-
} else if (to->status == ZEND_FIBER_STATUS_SHUTDOWN) {
430-
php_printf("<destroying '%p'>\n", to);
428+
if (to->flags & ZEND_FIBER_FLAG_DESTROYED) {
429+
php_printf("<destroying '%p'>\n", to);
430+
} else if (to->status != ZEND_FIBER_STATUS_DEAD) {
431+
php_printf("<resume '%p'>\n", to);
432+
}
431433
}
432434
}
433435
}
@@ -439,12 +441,14 @@ static void fiber_suspend_observer(zend_fiber *from, zend_fiber *to)
439441
if (from) {
440442
if (from->status == ZEND_FIBER_STATUS_SUSPENDED) {
441443
php_printf("<suspend '%p'>\n", from);
442-
} else if (from->status == ZEND_FIBER_STATUS_RETURNED) {
443-
php_printf("<returned '%p'>\n", from);
444-
} else if (from->status == ZEND_FIBER_STATUS_THREW) {
445-
php_printf("<threw '%p'>\n", from);
446-
} else if (from->status == ZEND_FIBER_STATUS_SHUTDOWN) {
447-
php_printf("<destroyed '%p'>\n", from);
444+
} else if (from->status == ZEND_FIBER_STATUS_DEAD) {
445+
if (from->flags & ZEND_FIBER_FLAG_THREW) {
446+
php_printf("<threw '%p'>\n", from);
447+
} else if (from->flags & ZEND_FIBER_FLAG_DESTROYED) {
448+
php_printf("<destroyed '%p'>\n", from);
449+
} else {
450+
php_printf("<returned '%p'>\n", from);
451+
}
448452
}
449453
}
450454
}

ext/zend_test/tests/observer_fiber_05.phpt

-2
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ $fiber->resume();
4444
<destroying '%s'>
4545
<!-- switching from fiber %s to %s -->
4646
<destroying '%s'>
47-
<destroyed '%s'>
4847
<!-- switching from fiber %s to %s -->
49-
<destroying '%s'>
5048
<destroyed '%s'>
5149
<!-- switching from fiber %s to 0 -->
5250
<destroyed '%s'>

0 commit comments

Comments
 (0)