Thanks to visit codestin.com
Credit goes to github.com

Skip to content

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

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

Merged
merged 1 commit into from
Sep 19, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 81 additions & 7 deletions src/Symfony/Component/Process/Process.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks :)

}
}

$commandline = $this->commandline;
Expand Down Expand Up @@ -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;
Expand All @@ -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();
}

/**
Expand All @@ -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'];
Expand All @@ -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'];
Expand Down Expand Up @@ -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().
*
Expand Down Expand Up @@ -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
*
Expand Down
Loading