@@ -853,7 +853,7 @@ static void async_stream_callback_resolve(
853853 * Optimized select() for PHP stream arrays using event reuse
854854 */
855855static zend_always_inline bool process_stream_array (zval * streams , async_poll_event events , zend_coroutine_t * coroutine ,
856- zval * read_streams_array , zval * write_streams_array , zval * except_streams_array , int * result ) {
856+ zval * read_streams , zval * write_streams , zval * except_streams , int * result ) {
857857
858858 if (streams == NULL || Z_TYPE_P (streams ) != IS_ARRAY ) {
859859 return true;
@@ -863,12 +863,14 @@ static zend_always_inline bool process_stream_array(zval *streams, async_poll_ev
863863 php_stream * stream ;
864864 zend_string * key ;
865865 zend_ulong num_key ;
866- int count = 0 ;
867866
868867 ZEND_HASH_FOREACH_KEY_VAL (Z_ARR_P (streams ), num_key , key , z_stream ) {
869868 ZVAL_DEREF (z_stream );
870869 php_stream_from_zval_no_verify (stream , z_stream );
871- if (stream == NULL ) continue ;
870+
871+ if (stream == NULL ) {
872+ continue ;
873+ }
872874
873875 // Try to get async event handle from socket streams first
874876 zend_async_poll_event_t * event_handle = NULL ;
@@ -882,6 +884,7 @@ static zend_always_inline bool process_stream_array(zval *streams, async_poll_ev
882884 || io_descriptor .fd == INVALID_IO_DESCRIPTOR )) {
883885 zend_throw_error (NULL , "Failed to cast stream to I/O descriptor" );
884886 * result = -1 ;
887+
885888 return false;
886889 }
887890
@@ -900,10 +903,15 @@ static zend_always_inline bool process_stream_array(zval *streams, async_poll_ev
900903 return false;
901904 }
902905
906+ // We add the IO descriptor event to the EventLoop without waiting
907+ // for the Waker to initiate work, in order to save on system calls.
908+ event_handle -> base .start (& event_handle -> base );
909+
903910 // And save it
904911 if (UNEXPECTED (PHP_STREAM_OPTION_RETURN_OK != php_stream_set_option (
905912 stream , PHP_STREAM_OPTION_ASYNC_EVENT_HANDLE , events , & event_handle )
906913 )) {
914+
907915 zend_throw_error (NULL , "Failed to set async event handle on stream" );
908916 * result = -1 ;
909917 return false;
@@ -927,22 +935,23 @@ static zend_always_inline bool process_stream_array(zval *streams, async_poll_ev
927935 }
928936
929937 // Save references to result arrays
930- callback -> read_streams = read_streams_array ;
931- callback -> write_streams = write_streams_array ;
932- callback -> except_streams = except_streams_array ;
938+ callback -> read_streams = read_streams ;
939+ callback -> write_streams = write_streams ;
940+ callback -> except_streams = except_streams ;
933941
934942 zend_async_resume_when (
935943 coroutine ,
936944 & event_handle -> base ,
937- true ,
945+ false ,
938946 NULL ,
939947 & callback -> callback
940948 );
941-
942- count ++ ;
943949 } ZEND_HASH_FOREACH_END ();
944950
945- return count ;
951+ // Now clean up the input array to prepare for results
952+ zend_hash_clean (Z_ARR_P (streams ));
953+
954+ return true;
946955}
947956
948957/**
@@ -982,7 +991,7 @@ static zend_always_inline bool process_stream_array(zval *streams, async_poll_ev
982991 *
983992 * @see select(2), php_poll2_async(), php_select_async()
984993 */
985- ZEND_API int php_stream_select_async (zval * read_streams , zval * write_streams , zval * except_streams , struct timeval * tv )
994+ ZEND_API int network_async_stream_select (zval * read_streams , zval * write_streams , zval * except_streams , struct timeval * tv )
986995{
987996 zend_coroutine_t * coroutine = ZEND_ASYNC_CURRENT_COROUTINE ;
988997
@@ -1005,15 +1014,14 @@ ZEND_API int php_stream_select_async(zval *read_streams, zval *write_streams, zv
10051014 // Initialize result counter
10061015 ZVAL_LONG (& coroutine -> waker -> result , 0 );
10071016
1008- // Clear result arrays first
1009- if (read_streams != NULL && Z_TYPE_P (read_streams ) == IS_ARRAY ) {
1010- zend_hash_clean (Z_ARR_P (read_streams ));
1017+ if (read_streams != NULL && Z_REFCOUNT_P (read_streams ) > 1 ) {
1018+ SEPARATE_ARRAY (read_streams );
10111019 }
1012- if (write_streams != NULL && Z_TYPE_P (write_streams ) == IS_ARRAY ) {
1013- zend_hash_clean ( Z_ARR_P ( write_streams ) );
1020+ if (write_streams != NULL && Z_REFCOUNT_P (write_streams ) > 1 ) {
1021+ SEPARATE_ARRAY ( write_streams );
10141022 }
1015- if (except_streams != NULL && Z_TYPE_P (except_streams ) == IS_ARRAY ) {
1016- zend_hash_clean ( Z_ARR_P ( except_streams ) );
1023+ if (except_streams != NULL && Z_REFCOUNT_P (except_streams ) > 1 ) {
1024+ SEPARATE_ARRAY ( except_streams );
10171025 }
10181026
10191027 // Process all stream arrays using the helper function
0 commit comments