X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Fshell%2FCommand.php;h=d6f95783f0dd5287d6665a745d869c0c0d01133d;hp=4f65e4d3922f45463b52c64f3134e1e97e304b3a;hb=ee56f00ddf0609082f8ae9a4dc3e6e1b6f54ddfd;hpb=ba00b23a1d6fea3f05c617d3df73d60ab28dfdf4 diff --git a/includes/shell/Command.php b/includes/shell/Command.php index 4f65e4d392..d6f95783f0 100644 --- a/includes/shell/Command.php +++ b/includes/shell/Command.php @@ -404,11 +404,20 @@ class Command { $eintr = defined( 'SOCKET_EINTR' ) ? SOCKET_EINTR : 4; $eintrMessage = "stream_select(): unable to select [$eintr]"; + /* The select(2) system call only guarantees a "sufficiently small write" + * can be made without blocking. And on Linux the read might block too + * in certain cases, although I don't know if any of them can occur here. + * Regardless, set all the pipes to non-blocking to avoid T184171. + */ + foreach ( $pipes as $pipe ) { + stream_set_blocking( $pipe, false ); + } + $running = true; $timeout = null; $numReadyPipes = 0; - while ( $running === true || $numReadyPipes !== 0 ) { + while ( $pipes && ( $running === true || $numReadyPipes !== 0 ) ) { if ( $running ) { $status = proc_get_status( $proc ); // If the process has terminated, switch to nonblocking selects @@ -465,14 +474,17 @@ class Command { } if ( $res === '' || $res === 0 ) { - // End of file - fclose( $pipes[$fd] ); - unset( $pipes[$fd] ); - if ( !$pipes ) { - break 2; + // End of file? + if ( feof( $pipe ) ) { + fclose( $pipes[$fd] ); + unset( $pipes[$fd] ); } } elseif ( $isWrite ) { - $buffers[$fd] = substr( $buffers[$fd], $res ); + $buffers[$fd] = (string)substr( $buffers[$fd], $res ); + if ( $buffers[$fd] === '' ) { + fclose( $pipes[$fd] ); + unset( $pipes[$fd] ); + } } else { $buffers[$fd] .= $res; if ( $fd === 3 && strpos( $res, "\n" ) !== false ) {