Capture signals and wait until child process exits to also exit, fixes #6059
parent
1a4f2174e4
commit
07645b9895
|
@ -17,6 +17,7 @@ use Composer\Util\Filesystem;
|
||||||
use Composer\Util\Platform;
|
use Composer\Util\Platform;
|
||||||
use Composer\Util\Silencer;
|
use Composer\Util\Silencer;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
|
use Seld\Signal\SignalHandler;
|
||||||
use Symfony\Component\Console\Application as BaseApplication;
|
use Symfony\Component\Console\Application as BaseApplication;
|
||||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||||
use Symfony\Component\Console\Helper\HelperSet;
|
use Symfony\Component\Console\Helper\HelperSet;
|
||||||
|
@ -93,7 +94,15 @@ class Application extends BaseApplication
|
||||||
date_default_timezone_set(Silencer::call('date_default_timezone_get'));
|
date_default_timezone_set(Silencer::call('date_default_timezone_get'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->io = new NullIO();
|
||||||
|
|
||||||
if (!$shutdownRegistered) {
|
if (!$shutdownRegistered) {
|
||||||
|
$signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) {
|
||||||
|
$this->io->writeError('Received '.$signal.', aborting', true, IOInterface::DEBUG);
|
||||||
|
|
||||||
|
$handler->exitWithLastSignal();
|
||||||
|
});
|
||||||
|
|
||||||
$shutdownRegistered = true;
|
$shutdownRegistered = true;
|
||||||
|
|
||||||
register_shutdown_function(static function (): void {
|
register_shutdown_function(static function (): void {
|
||||||
|
@ -107,8 +116,6 @@ class Application extends BaseApplication
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->io = new NullIO();
|
|
||||||
|
|
||||||
$this->initialWorkingDirectory = getcwd();
|
$this->initialWorkingDirectory = getcwd();
|
||||||
|
|
||||||
parent::__construct('Composer', Composer::getVersion());
|
parent::__construct('Composer', Composer::getVersion());
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
namespace Composer\EventDispatcher;
|
namespace Composer\EventDispatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Thrown when a script running an external process exits with a non-0 status code
|
||||||
|
*
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class ScriptExecutionException extends \RuntimeException
|
class ScriptExecutionException extends \RuntimeException
|
||||||
|
|
|
@ -14,6 +14,8 @@ namespace Composer\Util;
|
||||||
|
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Pcre\Preg;
|
use Composer\Pcre\Preg;
|
||||||
|
use Seld\Signal\SignalHandler;
|
||||||
|
use Symfony\Component\Process\Exception\ProcessSignaledException;
|
||||||
use Symfony\Component\Process\Process;
|
use Symfony\Component\Process\Process;
|
||||||
use Symfony\Component\Process\Exception\RuntimeException;
|
use Symfony\Component\Process\Exception\RuntimeException;
|
||||||
use React\Promise\Promise;
|
use React\Promise\Promise;
|
||||||
|
@ -125,6 +127,13 @@ class ProcessExecutor
|
||||||
$this->outputHandler($type, $buffer);
|
$this->outputHandler($type, $buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal) {
|
||||||
|
if ($this->io !== null) {
|
||||||
|
$this->io->writeError('Received '.$signal.', aborting when child process is done', true, IOInterface::DEBUG);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
$process->run($callback);
|
$process->run($callback);
|
||||||
|
|
||||||
if ($this->captureOutput && !is_callable($output)) {
|
if ($this->captureOutput && !is_callable($output)) {
|
||||||
|
@ -132,6 +141,14 @@ class ProcessExecutor
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->errorOutput = $process->getErrorOutput();
|
$this->errorOutput = $process->getErrorOutput();
|
||||||
|
} catch (ProcessSignaledException $e) {
|
||||||
|
if ($signalHandler->isTriggered()) {
|
||||||
|
// exiting as we were signaled and the child process exited too due to the signal
|
||||||
|
$signalHandler->exitWithLastSignal();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
$signalHandler->unregister();
|
||||||
|
}
|
||||||
|
|
||||||
return $process->getExitCode();
|
return $process->getExitCode();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue