Question

Consider this sample script:

<?php

$pipes = array();
$p = proc_open('cat', array(0 => STDIN, 1 => STDOUT, 2 => STDERR), $pipes);
fgetc(STDIN);

When /bin/sh is symlinked to /bin/dash (the Debian default), cat gets executed in a shell:

30760 pts/0    S+     0:00  |           \_ php f.php
30761 pts/0    S+     0:00  |               \_ sh -c cat
30762 pts/0    S+     0:00  |                   \_ cat

When /bin/sh is linked to /bin/bash however, cat is a direct child of php:

30786 pts/0    S+     0:00  |           \_ php f.php
30787 pts/0    S+     0:00  |               \_ cat

This is very annoying inconsistency that makes it impossible to reliably send signals to the spawned process (as the signal is sometimes received by a shell).

Why is proc_open behaving differently depending on where /bin/sh points to? Is there a way to not run a shell, even if /bin/sh is not bash?

Was it helpful?

Solution

PHP runs the command via /bin/sh in both cases, the difference is in the shells, not PHP. dash forks the process to run the command (cat in this case) and waits for it to finish. bash does an execve(), so it replaces its own process with cat.

They seem to have fixed it in later versions though: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=436466

Using bash or the latest version of dash should fix your problem, since the executed command gets the PID of the spawned shell and thus receives the signals.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top