New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.1][Process] Fix stop in non-sigchild environments #5543

Merged
merged 1 commit into from Sep 19, 2012
Jump to file or symbol
Failed to load files and symbols.
+441 −32
Diff settings

Always

Just for now

Add a Sigchild compatibility mode (set to false by default)

This mode is required to use a hack to determine if the process finished with success when PHP has been compiled with the --enable-sigchild option
  • Loading branch information...
romainneutron committed Sep 9, 2012
commit 7bafc69f38a3512eb15aad506959a4e7be162e52
@@ -11,6 +11,8 @@
namespace Symfony\Component\Process;
use Symfony\Component\Process\Exception\RuntimeException;
/**
* Process is a thin wrapper around proc_* functions to ease
* start independent PHP processes.
@@ -44,13 +46,16 @@ class Process
private $stdout;
private $stderr;
private $enhanceWindowsCompatibility;
private $enhanceSigchildCompatibility;
private $pipes;
private $process;
private $status = self::STATUS_READY;
private $fileHandles;
private $readBytes;
private static $sigchild;
/**
* Exit codes translation table.
*
@@ -134,6 +139,7 @@ public function __construct($commandline, $cwd = null, array $env = null, $stdin
$this->stdin = $stdin;
$this->setTimeout($timeout);
$this->enhanceWindowsCompatibility = true;
$this->enhanceSigchildCompatibility = !defined('PHP_WINDOWS_VERSION_BUILD') && $this->isSigchildEnabled();
$this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
}
@@ -216,9 +222,16 @@ public function start($callback = null)
array('pipe', 'r'), // stdin
array('pipe', 'w'), // stdout
array('pipe', 'w'), // stderr
array('pipe', 'w') // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
);
$this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';
if ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
// last exit code is output on the fourth pipe and caught to work around --enable-sigchild
$descriptors = array_merge($descriptors, array(array('pipe', 'w')));
$this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';
} else {
$this->commandline = 'exec ' . $this->commandline;

This comment has been minimized.

@schmittjoh

schmittjoh Sep 18, 2012

Contributor

Can you change this to only prepend exec for non-Windows environments?

@schmittjoh

schmittjoh Sep 18, 2012

Contributor

Can you change this to only prepend exec for non-Windows environments?

This comment has been minimized.

@romainneutron

romainneutron Sep 18, 2012

Member

This comment has been minimized.

@schmittjoh

schmittjoh Sep 18, 2012

Contributor

Great, thanks :)

@schmittjoh

schmittjoh Sep 18, 2012

Contributor

Great, thanks :)

}
}
$commandline = $this->commandline;
@@ -418,10 +431,16 @@ public function getErrorOutput()
*
* @return integer The exit status code
*
* @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
*
* @api
*/
public function getExitCode()
{
if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) {
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method');
}
$this->updateStatus();
return $this->exitcode;
@@ -435,28 +454,30 @@ public function getExitCode()
*
* @return string A string representation for the exit status code
*
* @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
*
* @see http://tldp.org/LDP/abs/html/exitcodes.html
* @see http://en.wikipedia.org/wiki/Unix_signal
*/
public function getExitCodeText()
{
$this->updateStatus();
$exitcode = $this->getExitCode();
return isset(self::$exitCodes[$this->exitcode]) ? self::$exitCodes[$this->exitcode] : 'Unknown error';
return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
}
/**
* Checks if the process ended successfully.
*
* @return Boolean true if the process ended successfully, false otherwise
*
* @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
*
* @api
*/
public function isSuccessful()
{
$this->updateStatus();
return 0 == $this->exitcode;
return 0 == $this->getExitCode();
}
/**
@@ -466,10 +487,16 @@ public function isSuccessful()
*
* @return Boolean
*
* @throws RuntimeException In case --enable-sigchild is activated
*
* @api
*/
public function hasBeenSignaled()
{
if ($this->isSigchildEnabled()) {
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
}
$this->updateStatus();
return $this->processInformation['signaled'];
@@ -482,10 +509,16 @@ public function hasBeenSignaled()
*
* @return integer
*
* @throws RuntimeException In case --enable-sigchild is activated
*
* @api
*/
public function getTermSignal()
{
if ($this->isSigchildEnabled()) {
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
}
$this->updateStatus();
return $this->processInformation['termsig'];
@@ -678,6 +711,30 @@ public function setEnhanceWindowsCompatibility($enhance)
$this->enhanceWindowsCompatibility = (Boolean) $enhance;
}
/**
* Return whether sigchild compatibility mode is activated or not
*
* @return Boolean
*/
public function getEnhanceSigchildCompatibility()
{
return $this->enhanceSigchildCompatibility;
}
/**
* Activate sigchild compatibility mode
*
* Sigchild compatibility mode is required to get the exit code and
* determine the success of a process when PHP has been compiled with
* the --enable-sigchild option
*
* @param Boolean $enhance
*/
public function setEnhanceSigchildCompatibility($enhance)
{
$this->enhanceSigchildCompatibility = (Boolean) $enhance;
}
/**
* Builds up the callback used by wait().
*
@@ -743,6 +800,23 @@ protected function updateOutput()
}
}
/**
* Return whether PHP has been compiled with the '--enable-sigchild' option or not
*
* @return Boolean
*/
protected function isSigchildEnabled()
{
if (null !== self::$sigchild) {
return self::$sigchild;
}
ob_start();
phpinfo(INFO_GENERAL);
return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
}
/**
* Handles the windows file handles fallbacks
*
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.