protected function newInstance($port)
{
if ($this->inShutdown) {
//when we are in the shutdown phase, we close all connections
//as a result it actually tries to reconnect the slave, but we forbid it in this phase.
return;
}
$keepClosed = false;
$bootstrapFailed = 0;
if (isset($this->slaves[$port])) {
$bootstrapFailed = $this->slaves[$port]['bootstrapFailed'];
$keepClosed = $this->slaves[$port]['keepClosed'];
if ($keepClosed) {
return;
}
}
if ($this->output->isVeryVerbose()) {
$this->output->writeln(sprintf("Start new worker #%d", $port));
}
$host = Utils::isWindows() ? 'tcp://127.0.0.1' : $this->getNewSlaveSocket($port);
$slave = ['ready' => false, 'pid' => null, 'port' => $port, 'closeWhenFree' => false, 'waitForRegister' => true, 'duringBootstrap' => false, 'bootstrapFailed' => $bootstrapFailed, 'keepClosed' => $keepClosed, 'busy' => false, 'requests' => 0, 'connections' => 0, 'connection' => null, 'host' => $host];
$bridge = var_export($this->getBridge(), true);
$bootstrap = var_export($this->getAppBootstrap(), true);
$config = ['port' => $slave['port'], 'host' => $slave['host'], 'session_path' => session_save_path(), 'controllerHost' => Utils::isWindows() ? 'tcp://127.0.0.1' : $this->controllerHost, 'app-env' => $this->getAppEnv(), 'debug' => $this->isDebug(), 'logging' => $this->isLogging(), 'static' => $this->isServingStatic()];
$config = var_export($config, true);
$dir = var_export(__DIR__, true);
$script = <<<EOF
<?php
set_time_limit(0);
require_once file_exists({$dir} . '/vendor/autoload.php')
? {$dir} . '/vendor/autoload.php'
: {$dir} . '/../../autoload.php';
require_once {$dir} . '/functions.php';
//global for all global functions
\\PHPPM\\ProcessSlave::\$slave = new \\PHPPM\\ProcessSlave({$bridge}, {$bootstrap}, {$config});
\\PHPPM\\ProcessSlave::\$slave->run();
EOF;
$commandline = $this->phpCgiExecutable;
$file = tempnam(sys_get_temp_dir(), 'dbg');
file_put_contents($file, $script);
register_shutdown_function('unlink', $file);
//we can not use -q since this disables basically all header support
//but since this is necessary at least in Symfony we can not use it.
//e.g. headers_sent() returns always true, although wrong.
$commandline .= ' -C ' . ProcessUtils::escapeArgument($file);
$descriptorspec = [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']];
$this->slaves[$port] = $slave;
$this->slaves[$port]['process'] = proc_open($commandline, $descriptorspec, $pipes);
$stderr = new \React\Stream\Stream($pipes[2], $this->loop);
$stderr->on('data', function ($data) use($port) {
if ($this->lastWorkerErrorPrintBy !== $port) {
$this->output->writeln("<info>--- Worker {$port} stderr ---</info>");
$this->lastWorkerErrorPrintBy = $port;
}
$this->output->write("<error>{$data}</error>");
});
$this->slaves[$port]['stderr'] = $stderr;
}