Skip to content

proc_open mixed up stderr and stdout when using pty for pipe #17983

Closed
@joelwurtz

Description

@joelwurtz

Description

We were having randomly bug in our ci where sometimes some test would failed because the stdout of a sub process launched by php was not complete.

We manage to make a reproducer, and it seems that sometimes stdout output would go to stderr.

Here is a reproducer :

<?php

[$reference] = run_process();

echo "Output Reference:\n";
echo $reference;
echo "\n";

for ($i=0; $i < 10_000; $i++) {
    if ($i > 0 && $i % 80 === 0) {
        echo "\n";
    }
    echo '.';
    [$output, $error] = run_process();

    // uncomment this line to make it works
//    $output .= $error;

    
    if ($output !== $reference) {
        throw new \RuntimeException("Output mismatch");
    }
}

function run_process(){
    $descriptors = [
        ['pty'],
        ['pty'],
        ['pty'],
    ];
    $pipes = [];

    $proc = proc_open(['cat', __FILE__], $descriptors, $pipes);
    $output = "";
    $error = "";

    stream_set_blocking($pipes[1], 0);
    stream_set_blocking($pipes[2], 0);

    while (proc_get_status($proc)['running']) {
        usleep(10); // longer timer will not cause the issue

        $output .= @stream_get_contents($pipes[1], -1);
        $error .= @stream_get_contents($pipes[2], -1);
    }

    $output .= @stream_get_contents($pipes[1], -1);
    $error .= @stream_get_contents($pipes[2], -1);

    return [$output, $error];
}

I suspect this have to do about having a pipe not ready or something mixed, having a longer timer before first read, reduce a lot the probability of error

See also symfony/symfony#59927

PHP Version

PHP 8.4

Operating System

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions