public function run(Container $container, callable $action)
{
$logger = LoopConfig::getLogger();
if ($this->running === 0) {
foreach ($this->loggers as $handler) {
$logger->addHandler($handler);
}
}
$this->running++;
try {
$buffer = '';
if ($this->ipc) {
ob_start(function (string $data, int $phase) use(&$buffer) {
$buffer .= $data;
return '';
}, 1, \PHP_OUTPUT_HANDLER_FLUSHABLE);
}
Loop::execute(function () use($container, $action, $logger, &$buffer) {
Loop::setErrorHandler(function (\Throwable $e) use($logger) {
$logger->critical('', ['exception' => $e]);
});
$watcher = Loop::repeat(500, function () use(&$buffer, $logger) {
if ($buffer !== '') {
try {
$this->ipc->sendOutput($buffer);
} finally {
$buffer = '';
}
}
});
Loop::unreference($watcher);
if ($this->contextName === 'development') {
$locator = $container->get(ResourceLocator::class);
$watcher = Loop::repeat(5000, function () use($locator) {
$locator->syncFiles();
});
Loop::unreference($watcher);
}
if ($this->ipc) {
$this->ipc->run();
}
$signal = function () {
if ($this->ipc) {
$this->ipc->stop();
}
Loop::stop();
};
// Shutdown on SIGTERM.
try {
Loop::onSignal(15, $signal);
} catch (UnsupportedFeatureException $e) {
// signal handling is not available...
}
$action();
});
} finally {
if ($this->ipc) {
\ob_end_clean();
}
$this->running--;
if ($this->running === 0) {
foreach ($this->loggers as $handler) {
$logger->removeHandler($handler);
}
}
}
}