amphp / process

An async process dispatcher for Amp.
MIT License
229 stars 32 forks source link

ProcessException with message 'Could not determine PID' #44

Closed rodion-k closed 3 years ago

rodion-k commented 4 years ago

The following code:

\Amp\Loop::run(function() {
    $process = new \Amp\Process\Process('diff <(echo 1) <(echo 2)');
    yield $process->start();
    yield $process->join();
});

Raises exception:

Amp\Process\ProcessException: Could not determine PID

vendor/amphp/process/lib/Internal/Posix/Runner.php:54
vendor/amphp/amp/lib/Loop/NativeDriver.php:201
vendor/amphp/amp/lib/Loop/NativeDriver.php:104
vendor/amphp/amp/lib/Loop/Driver.php:138
vendor/amphp/amp/lib/Loop/Driver.php:72
vendor/amphp/amp/lib/Loop.php:95
tests/CsvDiffIteratorTest.php:69

Actual command executed is: { (diff <(echo 1) <(echo 2)) <&3 3<&- 3>/dev/null & } 3<&0; trap "" INT TERM QUIT HUP;pid=$!; echo $pid >&3; wait $pid; RC=$?; echo $RC >&3; exit $RC

Executing it in terminal gives:

$ { (diff <(echo 1) <(echo 2)) <&3 3<&- 3>/dev/null & } 3<&0; trap "" INT TERM QUIT HUP;pid=$!; echo $pid >&3; wait $pid; RC=$?; echo $RC >&3
[1] 172
bash: 3: Bad file descriptor
1c1
< 1
---
> 2
[1]+  Exit 1                  ( diff <(echo 1) <(echo 2) ) 0<&3 3>&- 3> /dev/null
bash: 3: Bad file descriptor
ktomk commented 3 years ago

diff <(echo 1) <(echo 2) is a shell syntax not supported within the Posix standard, it works in Bash (and ZSH and some other)

/bin/bash -c 'diff <(echo 1) <(echo 2);'
1c1
< 1
---
> 2

but not in posix:

/bin/bash --posix -c 'diff <(echo 1) <(echo 2);'
/bin/bash: -c: line 0: syntax error near unexpected token `('
/bin/bash: -c: line 0: `diff <(echo 1) <(echo 2);'

the bash example only to show how it could be simulated, the actual shell in use is /bin/sh:

/bin/sh -c 'diff <(echo 1) <(echo 2);' 
/bin/sh: 1: Syntax error: "(" unexpected

This is equivalent with the long variant:

/bin/sh -c '{ (diff <(echo 1) <(echo 2)) <&3 3<&- 3>/dev/null & } 3<&0; trap "" INT TERM QUIT HUP;pid=$!; echo $pid >&3; wait $pid; RC=$?; echo $RC >&3; exit $RC' 3>&2
/bin/sh: 1: Syntax error: "(" unexpected

As no PID is being output on stream 3, it could not be determined, hence the

Could not determine PID

exception message.

Long description now, but it contains already the solution. Change the command to bash:

\Amp\Loop::run(function() {
    $process = new \Amp\Process\Process('/bin/bash -c "diff <(echo 1) <(echo 2)"');
    yield $process->start();
    yield $process->join();
});