@@ -1645,11 +1645,43 @@ function run_all_tests_parallel(array $test_files, array $env, $redir_tested): v
1645
1645
}
1646
1646
}
1647
1647
1648
+ /**
1649
+ * Calls fwrite and retries when network writes fail with errors such as "Resource temporarily unavailable"
1650
+ *
1651
+ * @param resource $stream the stream to fwrite to
1652
+ * @param string $data
1653
+ * @return int|false
1654
+ */
1655
+ function safe_fwrite ($ stream , string $ data )
1656
+ {
1657
+ // safe_fwrite was tested by adding $message['unused'] = str_repeat('a', 20_000_000); in send_message()
1658
+ // fwrites on tcp sockets can return false or less than strlen if the recipient is busy.
1659
+ // (e.g. fwrite(): Send of 577 bytes failed with errno=35 Resource temporarily unavailable)
1660
+ $ bytes_written = 0 ;
1661
+ while ($ bytes_written < strlen ($ data )) {
1662
+ $ n = @fwrite ($ stream , substr ($ data , $ bytes_written ));
1663
+ if ($ n === false ) {
1664
+ $ write_streams = [$ stream ];
1665
+ $ read_streams = [];
1666
+ $ except_streams = [];
1667
+ /* Wait for up to 10 seconds for the stream to be ready to write again. */
1668
+ stream_select ($ read_streams , $ write_streams , $ except_streams , 10 );
1669
+ $ n = @fwrite ($ stream , substr ($ data , $ bytes_written ));
1670
+ if ($ n === false ) {
1671
+ echo "ERROR: send_message() Failed to write chunk after stream_select: " . error_get_last ()['message ' ] . "\n" ;
1672
+ return false ;
1673
+ }
1674
+ }
1675
+ $ bytes_written += $ n ;
1676
+ }
1677
+ return $ bytes_written ;
1678
+ }
1679
+
1648
1680
function send_message ($ stream , array $ message ): void
1649
1681
{
1650
1682
$ blocking = stream_get_meta_data ($ stream )["blocked " ];
1651
1683
stream_set_blocking ($ stream , true );
1652
- fwrite ($ stream , base64_encode (serialize ($ message )) . "\n" );
1684
+ safe_fwrite ($ stream , base64_encode (serialize ($ message )) . "\n" );
1653
1685
stream_set_blocking ($ stream , $ blocking );
1654
1686
}
1655
1687
0 commit comments