@@ -406,7 +406,7 @@ ZEND_API zend_async_event_callback_t * zend_async_event_callback_new(zend_async_
406
406
return event_callback ;
407
407
}
408
408
409
- static void coroutine_event_callback_dispose (zend_async_event_callback_t * callback , zend_async_event_t * event );
409
+ void coroutine_event_callback_dispose (zend_async_event_callback_t * callback , zend_async_event_t * event );
410
410
411
411
ZEND_API zend_coroutine_event_callback_t * zend_async_coroutine_callback_new (
412
412
zend_coroutine_t * coroutine , zend_async_event_callback_fn callback , size_t size
@@ -552,14 +552,18 @@ static void coroutine_event_callback_dispose(zend_async_event_callback_t *callba
552
552
553
553
callback -> ref_count = 0 ;
554
554
555
- zend_async_waker_t * waker = ((zend_coroutine_event_callback_t * ) callback )-> coroutine -> waker ;
555
+ const zend_coroutine_t * coroutine = ((zend_coroutine_event_callback_t * ) callback )-> coroutine ;
556
556
557
- if (event != NULL && waker != NULL ) {
558
- // remove the event from the waker
559
- zend_hash_index_del (& waker -> events , (zend_ulong )event );
557
+ if (EXPECTED (coroutine != NULL )) {
558
+ zend_async_waker_t * waker = coroutine -> waker ;
560
559
561
- if (waker -> triggered_events != NULL ) {
562
- zend_hash_index_del (waker -> triggered_events , (zend_ulong )event );
560
+ if (event != NULL && waker != NULL ) {
561
+ // remove the event from the waker
562
+ zend_hash_index_del (& waker -> events , (zend_ulong )event );
563
+
564
+ if (waker -> triggered_events != NULL ) {
565
+ zend_hash_index_del (waker -> triggered_events , (zend_ulong )event );
566
+ }
563
567
}
564
568
}
565
569
@@ -582,6 +586,15 @@ ZEND_API void zend_async_waker_add_triggered_event(zend_coroutine_t *coroutine,
582
586
}
583
587
}
584
588
589
+ ZEND_API bool zend_async_waker_is_event_exists (zend_coroutine_t * coroutine , zend_async_event_t * event )
590
+ {
591
+ if (UNEXPECTED (coroutine -> waker == NULL )) {
592
+ return false;
593
+ }
594
+
595
+ return zend_hash_index_find (& coroutine -> waker -> events , (zend_ulong )event ) != NULL ;
596
+ }
597
+
585
598
ZEND_API void zend_async_resume_when (
586
599
zend_coroutine_t * coroutine ,
587
600
zend_async_event_t * event ,
@@ -590,6 +603,8 @@ ZEND_API void zend_async_resume_when(
590
603
zend_coroutine_event_callback_t * event_callback
591
604
)
592
605
{
606
+ bool locally_allocated_callback = false;
607
+
593
608
if (UNEXPECTED (ZEND_ASYNC_EVENT_IS_CLOSED (event ))) {
594
609
zend_throw_error (NULL , "The event cannot be used after it has been terminated" );
595
610
return ;
@@ -610,6 +625,7 @@ ZEND_API void zend_async_resume_when(
610
625
event_callback -> base .ref_count = 1 ;
611
626
event_callback -> base .callback = callback ;
612
627
event_callback -> base .dispose = coroutine_event_callback_dispose ;
628
+ locally_allocated_callback = true;
613
629
}
614
630
615
631
// Set up the default dispose function if not set
@@ -627,6 +643,10 @@ ZEND_API void zend_async_resume_when(
627
643
event -> add_callback (event , & event_callback -> base );
628
644
629
645
if (UNEXPECTED (EG (exception ) != NULL )) {
646
+ if (locally_allocated_callback ) {
647
+ event_callback -> base .dispose (& event_callback -> base , event );
648
+ }
649
+
630
650
if (trans_event ) {
631
651
event -> dispose (event );
632
652
}
@@ -640,7 +660,18 @@ ZEND_API void zend_async_resume_when(
640
660
trigger -> callback = & event_callback -> base ;
641
661
642
662
if (UNEXPECTED (zend_hash_index_add_ptr (& coroutine -> waker -> events , (zend_ulong )event , trigger ) == NULL )) {
643
- zend_throw_error (NULL , "Failed to add event to the waker" );
663
+ efree (trigger );
664
+
665
+ if (locally_allocated_callback ) {
666
+ event_callback -> base .dispose (& event_callback -> base , event );
667
+ }
668
+
669
+ if (trans_event ) {
670
+ event -> dispose (event );
671
+ }
672
+
673
+ zend_throw_error (NULL , "Failed to add event to the waker: maybe event already exists" );
674
+
644
675
return ;
645
676
}
646
677
}
0 commit comments