/** * @param Exception $exception */ public function logException(Exception $exception) { $formatter = new CM_ExceptionHandling_Formatter_Plain_Log(); try { if ($exception instanceof CM_Exception) { $log = $exception->getLog(); $metaInfo = $exception->getMetaInfo(); } else { $log = new CM_Paging_Log_Error(); $metaInfo = null; } $log->add($formatter->formatException($exception), $metaInfo); } catch (Exception $loggerException) { $logEntry = '[' . date('d.m.Y - H:i:s', time()) . ']' . PHP_EOL; $logEntry .= '### Cannot log error: ' . PHP_EOL; $logEntry .= $formatter->formatException($loggerException); $logEntry .= '### Original Exception: ' . PHP_EOL; $logEntry .= $formatter->formatException($exception) . PHP_EOL; $logFile = $this->_getLogFile(); $logFile->ensureParentDirectory(); $logFile->append($logEntry); } }
/** * @runInSeparateProcess * @preserveGlobalState disabled */ public function testKillChildrenSigKill() { $loopEcho = function () { while (true) { usleep(50 * 1000); echo "hello\n"; } }; $loopEchoStayinAlive = function () { pcntl_signal(SIGTERM, function () { echo "Well, you can tell by the way I use my walk\n I'm a woman's man, no time to talk\n"; }, false); while (true) { usleep(50 * 1000); echo "hello\n"; } }; $process = CM_Process::getInstance(); $process->fork($loopEcho); $process->fork($loopEchoStayinAlive); $pidListBefore = $this->_getChildrenPidList(); $timeStart = microtime(true); $process->killChildren(0.5); $this->assertCount(2, $pidListBefore); $this->assertCount(0, $this->_getChildrenPidList()); $this->assertSameTime(0.5, microtime(true) - $timeStart, 0.15); $logError = new CM_Paging_Log_Error(); $this->assertSame(1, $logError->getCount()); $this->assertContains('killing with signal `9`', $logError->getItem(0)['msg']); }
/** * @param float|null $timeoutKill */ public function killChildren($timeoutKill = null) { if (null === $timeoutKill) { $timeoutKill = 30; } $timeoutKill = (double) $timeoutKill; $signal = SIGTERM; $timeStart = microtime(true); $timeoutReached = false; $timeOutput = $timeStart; while (!empty($this->_forkHandlerList)) { $timeNow = microtime(true); $timePassed = $timeNow - $timeStart; if ($timePassed > $timeoutKill) { $signal = SIGKILL; $timeoutReached = true; } if ($timeNow > $timeOutput + 2 || $timeoutReached) { $message = join(' ', [count($this->_forkHandlerList) . ' children remaining', 'after ' . round($timePassed, 1) . ' seconds,', 'killing with signal `' . $signal . '`...']); echo $message . PHP_EOL; if ($timeoutReached) { $logError = new CM_Paging_Log_Error(); $logError->add($message, ['pid' => $this->getProcessId(), 'argv' => join(' ', $this->getArgv())]); } $timeOutput = $timeNow; } foreach ($this->_forkHandlerList as $forkHandler) { posix_kill($forkHandler->getPid(), $signal); } usleep(1000000 * 0.05); foreach ($this->_forkHandlerList as $forkHandler) { $pid = pcntl_waitpid($forkHandler->getPid(), $status, WNOHANG); if ($pid > 0 || !$this->isRunning($pid)) { $forkHandlerSequence = $this->_getForkHandlerSequenceByPid($forkHandler->getPid()); $forkHandler = $this->_forkHandlerList[$forkHandlerSequence]; $forkHandler->closeIpcStream(); unset($this->_forkHandlerList[$forkHandlerSequence]); if (!$this->_hasForks()) { $this->unbind('exit', [$this, 'killChildren']); } } } } }