@@ -120,21 +120,27 @@ static ssize_t php_sockop_write(php_stream *stream, const char *buf, size_t coun
120120 return didwrite ;
121121}
122122
123- static void php_sock_stream_wait_for_data (php_stream * stream , php_netstream_data_t * sock )
123+ static void php_sock_stream_wait_for_data (php_stream * stream , php_netstream_data_t * sock , bool has_buffered_data )
124124{
125125 int retval ;
126- struct timeval * ptimeout ;
126+ struct timeval * ptimeout , zero_timeout ;
127127
128128 if (!sock || sock -> socket == -1 ) {
129129 return ;
130130 }
131131
132132 sock -> timeout_event = 0 ;
133133
134- if (sock -> timeout .tv_sec == -1 )
134+ if (has_buffered_data ) {
135+ /* If there is already buffered data, use no timeout. */
136+ zero_timeout .tv_sec = 0 ;
137+ zero_timeout .tv_usec = 0 ;
138+ ptimeout = & zero_timeout ;
139+ } else if (sock -> timeout .tv_sec == -1 ) {
135140 ptimeout = NULL ;
136- else
141+ } else {
137142 ptimeout = & sock -> timeout ;
143+ }
138144
139145 while (1 ) {
140146 retval = php_pollfd_for (sock -> socket , PHP_POLLREADABLE , ptimeout );
@@ -153,21 +159,37 @@ static void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data
153159static ssize_t php_sockop_read (php_stream * stream , char * buf , size_t count )
154160{
155161 php_netstream_data_t * sock = (php_netstream_data_t * )stream -> abstract ;
156- ssize_t nr_bytes = 0 ;
157- int err ;
158162
159163 if (!sock || sock -> socket == -1 ) {
160164 return -1 ;
161165 }
162166
167+ int recv_flags = 0 ;
168+ /* Special handling for blocking read. */
163169 if (sock -> is_blocked ) {
164- php_sock_stream_wait_for_data (stream , sock );
165- if (sock -> timeout_event )
166- return -1 ;
170+ /* Find out if there is any data buffered from the previous read. */
171+ bool has_buffered_data = stream -> didread > 0 ;
172+ /* No need to wait if there is any data buffered or no timeout. */
173+ bool dont_wait = has_buffered_data ||
174+ (sock -> timeout .tv_sec == 0 && sock -> timeout .tv_usec == 0 );
175+ /* Set MSG_DONTWAIT if no wait is needed or there is unlimited timeout which was
176+ * added by fix for #41984 commited in 9343c5404. */
177+ if (dont_wait || sock -> timeout .tv_sec != -1 ) {
178+ recv_flags = MSG_DONTWAIT ;
179+ }
180+ /* If the wait is needed or it is a platform without MSG_DONTWAIT support (e.g. Windows),
181+ * then poll for data. */
182+ if (!dont_wait || MSG_DONTWAIT == 0 ) {
183+ php_sock_stream_wait_for_data (stream , sock , has_buffered_data );
184+ if (sock -> timeout_event ) {
185+ /* It is ok to timeout if there is any data buffered so return 0, otherwise -1. */
186+ return has_buffered_data ? 0 : -1 ;
187+ }
188+ }
167189 }
168190
169- nr_bytes = recv (sock -> socket , buf , XP_SOCK_BUF_SIZE (count ), ( sock -> is_blocked && sock -> timeout . tv_sec != -1 ) ? MSG_DONTWAIT : 0 );
170- err = php_socket_errno ();
191+ ssize_t nr_bytes = recv (sock -> socket , buf , XP_SOCK_BUF_SIZE (count ), recv_flags );
192+ int err = php_socket_errno ();
171193
172194 if (nr_bytes < 0 ) {
173195 if (PHP_IS_TRANSIENT_ERROR (err )) {
0 commit comments