xref: /PHP-8.4/ext/standard/tests/file/bug60120.phpt (revision dd44a933)
1--TEST--
2Bug #60120 (proc_open hangs when data in stdin/out/err is getting larger or equal to 2048)
3--SKIPIF--
4<?php
5$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
6if (!$php) {
7    die("skip No php executable defined\n");
8}
9if (PHP_OS_FAMILY === 'Windows') die('skip not for Windows');
10?>
11--FILE--
12<?php
13
14error_reporting(E_ALL);
15
16$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
17$cmd = $php . ' -r "\$in = file_get_contents(\'php://stdin\'); fwrite(STDOUT, \$in); fwrite(STDERR, \$in);"';
18$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
19$stdin = str_repeat('*', 2049 );
20
21$options = array_merge(array('suppress_errors' => true, 'bypass_shell' => false));
22$process = proc_open($cmd, $descriptors, $pipes, getcwd(), array(), $options);
23
24foreach ($pipes as $pipe) {
25    stream_set_blocking($pipe, false);
26}
27$writePipes = array($pipes[0]);
28$stdinLen = strlen($stdin);
29$stdinOffset = 0;
30
31unset($pipes[0]);
32
33$procOutput = [];
34while ($pipes || $writePipes) {
35    $r = $pipes;
36    $w = $writePipes;
37    $e = null;
38    $n = stream_select($r, $w, $e, 60);
39
40    if (false === $n) {
41        break;
42    } elseif ($n === 0) {
43        proc_terminate($process);
44
45    }
46    if ($w) {
47        $written = fwrite($writePipes[0], substr($stdin, $stdinOffset), 8192);
48        if (false !== $written) {
49            $stdinOffset += $written;
50        } else {
51            die('Failed to write to pipe');
52        }
53        if ($stdinOffset >= $stdinLen) {
54            fclose($writePipes[0]);
55            $writePipes = null;
56        }
57    }
58
59    foreach ($r as $pipe) {
60        $type = array_search($pipe, $pipes);
61        $data = fread($pipe, 8192);
62        if (feof($pipe)) {
63            fclose($pipe);
64            unset($pipes[$type]);
65        } elseif (false === $data) {
66            die('Failed to read from pipe');
67        } else {
68            $procOutput[$type] = ($procOutput[$type] ?? '') . $data;
69        }
70    }
71}
72foreach ($procOutput as $output) {
73    if ($output !== $stdin) {
74        die('Output does not match input: ' . $output);
75    }
76}
77echo "OK.";
78?>
79--EXPECT--
80OK.
81