@@ -58,24 +58,26 @@ extern transfer_t jump_fcontext(fcontext_t to, void *vp);
58
58
59
59
#define ZEND_FIBER_DEFAULT_PAGE_SIZE 4096
60
60
61
- #define ZEND_FIBER_BACKUP_EG (stack , stack_page_size , execute_data , error_reporting , trace_num ) do { \
61
+ #define ZEND_FIBER_BACKUP_EG (stack , stack_page_size , execute_data , error_reporting , trace_num , bailout ) do { \
62
62
stack = EG(vm_stack); \
63
63
stack->top = EG(vm_stack_top); \
64
64
stack->end = EG(vm_stack_end); \
65
65
stack_page_size = EG(vm_stack_page_size); \
66
66
execute_data = EG(current_execute_data); \
67
67
error_reporting = EG(error_reporting); \
68
68
trace_num = EG(jit_trace_num); \
69
+ bailout = EG(bailout); \
69
70
} while (0)
70
71
71
- #define ZEND_FIBER_RESTORE_EG (stack , stack_page_size , execute_data , error_reporting , trace_num ) do { \
72
+ #define ZEND_FIBER_RESTORE_EG (stack , stack_page_size , execute_data , error_reporting , trace_num , bailout ) do { \
72
73
EG(vm_stack) = stack; \
73
74
EG(vm_stack_top) = stack->top; \
74
75
EG(vm_stack_end) = stack->end; \
75
76
EG(vm_stack_page_size) = stack_page_size; \
76
77
EG(current_execute_data) = execute_data; \
77
78
EG(error_reporting) = error_reporting; \
78
79
EG(jit_trace_num) = trace_num; \
80
+ EG(bailout) = bailout; \
79
81
} while (0)
80
82
81
83
#if defined(MAP_STACK ) && !defined(__FreeBSD__ ) && !defined(__FreeBSD_kernel__ )
@@ -241,12 +243,13 @@ static void zend_fiber_suspend(zend_fiber *fiber)
241
243
zend_execute_data * execute_data ;
242
244
int error_reporting ;
243
245
uint32_t jit_trace_num ;
246
+ JMP_BUF * bailout ;
244
247
245
- ZEND_FIBER_BACKUP_EG (stack , stack_page_size , execute_data , error_reporting , jit_trace_num );
248
+ ZEND_FIBER_BACKUP_EG (stack , stack_page_size , execute_data , error_reporting , jit_trace_num , bailout );
246
249
247
250
zend_fiber_suspend_context (& fiber -> context );
248
251
249
- ZEND_FIBER_RESTORE_EG (stack , stack_page_size , execute_data , error_reporting , jit_trace_num );
252
+ ZEND_FIBER_RESTORE_EG (stack , stack_page_size , execute_data , error_reporting , jit_trace_num , bailout );
250
253
}
251
254
252
255
static void zend_fiber_switch_to (zend_fiber * fiber )
@@ -257,53 +260,30 @@ static void zend_fiber_switch_to(zend_fiber *fiber)
257
260
zend_execute_data * execute_data ;
258
261
int error_reporting ;
259
262
uint32_t jit_trace_num ;
263
+ JMP_BUF * bailout ;
260
264
261
265
previous = EG (current_fiber );
262
266
263
267
zend_observer_fiber_switch_notify (previous , fiber );
264
268
265
- ZEND_FIBER_BACKUP_EG (stack , stack_page_size , execute_data , error_reporting , jit_trace_num );
269
+ ZEND_FIBER_BACKUP_EG (stack , stack_page_size , execute_data , error_reporting , jit_trace_num , bailout );
266
270
267
271
EG (current_fiber ) = fiber ;
268
272
269
273
zend_fiber_switch_context (& fiber -> context );
270
274
271
275
EG (current_fiber ) = previous ;
272
276
273
- ZEND_FIBER_RESTORE_EG (stack , stack_page_size , execute_data , error_reporting , jit_trace_num );
277
+ ZEND_FIBER_RESTORE_EG (stack , stack_page_size , execute_data , error_reporting , jit_trace_num , bailout );
274
278
275
279
zend_observer_fiber_switch_notify (fiber , previous );
276
280
277
- if (UNEXPECTED (EG (fiber_error )) && fiber -> status != ZEND_FIBER_STATUS_SHUTDOWN ) {
278
- if (previous ) {
279
- zend_fiber_suspend (previous ); // Still in fiber, suspend again until in {main}.
280
- abort (); // This fiber should never be resumed.
281
- }
282
-
283
- zend_error_info * error = EG (fiber_error );
284
- zend_error_zstr_at (error -> type , error -> filename , error -> lineno , error -> message );
281
+ if (UNEXPECTED (fiber -> status == ZEND_FIBER_STATUS_BAILOUT )) {
282
+ // zend_bailout() was called in the fiber, so call it again in the previous fiber or {main}.
283
+ zend_bailout ();
285
284
}
286
285
}
287
286
288
- ZEND_COLD void zend_error_suspend_fiber (
289
- int orig_type , zend_string * error_filename , uint32_t error_lineno , zend_string * message )
290
- {
291
- ZEND_ASSERT (EG (current_fiber ) && "Must be within an active fiber!" );
292
- ZEND_ASSERT (orig_type & E_FATAL_ERRORS && "Error type must be fatal" );
293
-
294
- zend_error_info * error = emalloc (sizeof (zend_error_info ));
295
-
296
- error -> type = orig_type ;
297
- error -> filename = error_filename ;
298
- error -> lineno = error_lineno ;
299
- error -> message = message ;
300
-
301
- EG (fiber_error ) = error ;
302
-
303
- zend_fiber_suspend (EG (current_fiber ));
304
-
305
- abort (); // This fiber should never be resumed.
306
- }
307
287
308
288
static zend_always_inline zend_vm_stack zend_fiber_vm_stack_alloc (size_t size )
309
289
{
@@ -348,21 +328,25 @@ static void ZEND_STACK_ALIGNED zend_fiber_execute(zend_fiber_context *context)
348
328
349
329
fiber -> status = ZEND_FIBER_STATUS_RUNNING ;
350
330
351
- zend_call_function (& fiber -> fci , & fiber -> fci_cache );
331
+ zend_first_try {
332
+ zend_call_function (& fiber -> fci , & fiber -> fci_cache );
352
333
353
- zval_ptr_dtor (& fiber -> fci .function_name );
334
+ zval_ptr_dtor (& fiber -> fci .function_name );
354
335
355
- if (EG (exception )) {
356
- if (fiber -> status == ZEND_FIBER_STATUS_SHUTDOWN ) {
357
- if (EXPECTED (zend_is_graceful_exit (EG (exception )) || zend_is_unwind_exit (EG (exception )))) {
358
- zend_clear_exception ();
336
+ if (EG (exception )) {
337
+ if (fiber -> status == ZEND_FIBER_STATUS_SHUTDOWN ) {
338
+ if (EXPECTED (zend_is_graceful_exit (EG (exception )) || zend_is_unwind_exit (EG (exception )))) {
339
+ zend_clear_exception ();
340
+ }
341
+ } else {
342
+ fiber -> status = ZEND_FIBER_STATUS_THREW ;
359
343
}
360
344
} else {
361
- fiber -> status = ZEND_FIBER_STATUS_THREW ;
345
+ fiber -> status = ZEND_FIBER_STATUS_RETURNED ;
362
346
}
363
- } else {
364
- fiber -> status = ZEND_FIBER_STATUS_RETURNED ;
365
- }
347
+ } zend_catch {
348
+ fiber -> status = ZEND_FIBER_STATUS_BAILOUT ;
349
+ } zend_end_try ();
366
350
367
351
zend_vm_stack_destroy ();
368
352
fiber -> execute_data = NULL ;
@@ -512,13 +496,7 @@ ZEND_METHOD(Fiber, suspend)
512
496
513
497
if (fiber -> status == ZEND_FIBER_STATUS_SHUTDOWN ) {
514
498
// This occurs when the fiber is GC'ed while suspended.
515
- if (EG (fiber_error )) {
516
- // Throw UnwindExit so finally blocks are not executed on fatal error.
517
- zend_throw_unwind_exit ();
518
- } else {
519
- // Otherwise throw GracefulExit to execute finally blocks.
520
- zend_throw_graceful_exit ();
521
- }
499
+ zend_throw_graceful_exit ();
522
500
RETURN_THROWS ();
523
501
}
524
502
@@ -718,5 +696,4 @@ void zend_register_fiber_ce(void)
718
696
void zend_fiber_init (void )
719
697
{
720
698
EG (current_fiber ) = NULL ;
721
- EG (fiber_error ) = NULL ;
722
699
}
0 commit comments