@@ -793,15 +793,23 @@ typedef struct async_stream_callback_s {
793793 struct async_stream_callback_s * next ; // For linked list
794794} async_stream_callback_t ;
795795
796- static zend_always_inline void add_stream_to_array (zval * array , zval * key , zval * stream_zval ) {
797- if (array == NULL ) return ;
798-
796+ static zend_always_inline void add_stream_to_array (zval * array , zval * key , zval * stream_zval )
797+ {
798+ if (array == NULL ) {
799+ return ;
800+ }
801+
802+ if (Z_REFCOUNT_P (array ) > 1 ) {
803+ SEPARATE_ARRAY (array );
804+ }
805+
799806 zval * dest_elem ;
800807 if (Z_TYPE_P (key ) == IS_STRING ) {
801808 dest_elem = zend_hash_add (Z_ARR_P (array ), Z_STR_P (key ), stream_zval );
802809 } else {
803810 dest_elem = zend_hash_index_add (Z_ARR_P (array ), Z_LVAL_P (key ), stream_zval );
804811 }
812+
805813 if (dest_elem ) zval_add_ref (dest_elem );
806814}
807815
@@ -869,7 +877,7 @@ static zend_always_inline bool process_stream_array(zval *streams, async_poll_ev
869877 php_stream_from_zval_no_verify (stream , z_stream );
870878
871879 if (stream == NULL ) {
872- continue ;
880+ return false ;
873881 }
874882
875883 // Try to get async event handle from socket streams first
@@ -948,6 +956,10 @@ static zend_always_inline bool process_stream_array(zval *streams, async_poll_ev
948956 );
949957 } ZEND_HASH_FOREACH_END ();
950958
959+ if (Z_REFCOUNT_P (streams ) > 1 ) {
960+ SEPARATE_ARRAY (streams );
961+ }
962+
951963 // Now clean up the input array to prepare for results
952964 zend_hash_clean (Z_ARR_P (streams ));
953965
@@ -1014,16 +1026,6 @@ ZEND_API int network_async_stream_select(zval *read_streams, zval *write_streams
10141026 // Initialize result counter
10151027 ZVAL_LONG (& coroutine -> waker -> result , 0 );
10161028
1017- if (read_streams != NULL && Z_REFCOUNT_P (read_streams ) > 1 ) {
1018- SEPARATE_ARRAY (read_streams );
1019- }
1020- if (write_streams != NULL && Z_REFCOUNT_P (write_streams ) > 1 ) {
1021- SEPARATE_ARRAY (write_streams );
1022- }
1023- if (except_streams != NULL && Z_REFCOUNT_P (except_streams ) > 1 ) {
1024- SEPARATE_ARRAY (except_streams );
1025- }
1026-
10271029 // Process all stream arrays using the helper function
10281030 if (UNEXPECTED (!process_stream_array (read_streams , ASYNC_READABLE , coroutine , read_streams , write_streams , except_streams , & result ))) {
10291031 goto cleanup ;
@@ -1035,6 +1037,10 @@ ZEND_API int network_async_stream_select(zval *read_streams, zval *write_streams
10351037 goto cleanup ;
10361038 }
10371039
1040+ if (coroutine -> waker -> events .nNumOfElements == 0 ) {
1041+ goto cleanup ;
1042+ }
1043+
10381044 // Suspend until events occur or timeout
10391045 ZEND_ASYNC_SUSPEND ();
10401046 IF_EXCEPTION_GOTO_ERROR ;
0 commit comments