Skip to content

Commit 09dbef1

Browse files
committed
php#53: * fixes to STREAM test behavior
1 parent 1cd40d5 commit 09dbef1

File tree

3 files changed

+28
-20
lines changed

3 files changed

+28
-20
lines changed

ext/standard/streamsfuncs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ PHP_FUNCTION(stream_select)
753753
tv_async.tv_usec = usecnull ? 0 : usec;
754754
tv_p_async = &tv_async;
755755
}
756-
retval = php_stream_select_async(r_array, w_array, e_array, tv_p_async);
756+
retval = network_async_stream_select(r_array, w_array, e_array, tv_p_async);
757757
RETURN_LONG(retval >= 0 ? retval : 0);
758758
}
759759

main/network_async.c

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ static void async_stream_callback_resolve(
853853
* Optimized select() for PHP stream arrays using event reuse
854854
*/
855855
static 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

main/network_async.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ ZEND_API int network_async_await_stream_socket(php_netstream_data_t *sock, short
2727

2828
ZEND_API int php_poll2_async(php_pollfd *ufds, unsigned int nfds, int timeout);
2929
ZEND_API int php_select_async(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv);
30-
ZEND_API int php_stream_select_async(zval *read_streams, zval *write_streams, zval *except_streams, struct timeval *tv);
30+
ZEND_API int network_async_stream_select(zval *read_streams, zval *write_streams, zval *except_streams, struct timeval *tv);
3131

3232
ZEND_API int php_network_getaddrinfo_async(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
3333
ZEND_API struct hostent* php_network_gethostbyname_async(const char *name);

0 commit comments

Comments
 (0)