function __construct() { $this->logger = Logger::getLogger(__CLASS__); $this->db = $this->getContainer()->adodb; $this->lastCleanup = new Scalr_System_Ipc_Shm(array("name" => "scalr.cronjob.poller.lastCleanup")); $this->cleanupSem = sem_get(Scalr_System_OS::getInstance()->tok("scalr.cronjob.poller.cleanupSem")); }
/** * @param array $config * @key string [name] * @key int [key] */ function __construct($config = array()) { foreach ($config as $k => $v) { if (property_exists($this, $k)) { $this->{$k} = $v; } } $this->logger = Logger::getLogger(__CLASS__); if (!isset($this->key) && $config["name"]) { $this->key = Scalr_System_OS::getInstance()->tok($config["name"]); //$this->logger->error(sprintf("Shm key 0x%08x from name '%s' is generated", $this->key, $config["name"])); } $this->logger->debug(sprintf("Initialize shm segment (key: 0x%08x)", $this->key)); // TODO: check errors $this->shm = shm_attach($this->key); if (!$this->shm) { throw new Scalr_System_Ipc_Exception(sprintf("shm_attach failed for key 0x%08x", $this->key)); } }
/** * @param $config * @key int $key * @key string $name * @key int $perms * @key int $maxMsgSize * @key bool $blocking * @key int $blockingTimeout * @key bool $autoInit Initialize all component resources immediately in constructor (default false) * @return Scalr_System_Ipc_ShmQueue */ function __construct($config) { if (!function_exists('msg_get_queue')) { throw new Scalr_System_Ipc_Exception('msg_* functions are required'); } foreach ($config as $k => $v) { if (property_exists($this, $k)) { $this->{$k} = $v; } } $this->logger = Logger::getLogger(__CLASS__); if (!isset($this->key) && $config["name"]) { $this->key = Scalr_System_OS::getInstance()->tok($config["name"]); $this->logger->debug(sprintf("Queue key 0x%08x from name '%s' is generated", $this->key, $config["name"])); } if ($config["autoInit"]) { $this->init(); } }
protected function forkChild($useBarrier = true) { $this->logger->info("Fork child process"); $pid = pcntl_fork(); if ($pid == -1) { // Cannot fork child throw new Scalr_System_Ipc_Exception("Cannot fork child process"); } else { if ($pid) { // Current process $this->logger->info(sprintf("Child PID: %s was forked", $pid)); $this->childs[$pid] = array('pid' => $pid, 'workStartTime' => false, 'termStartTime' => false); $this->worker->childForked($pid); } else { // Child process try { $this->isChild = true; $this->childPid = posix_getpid(); $this->logger->info("Starting..."); $this->fireChildEvent("start"); if (!$useBarrier) { $this->ready = true; } else { /* $stat = new Scalr_System_Ipc_WorkerStat(); $stat->pid = $this->childPid; $stat->startTime = microtime(true); $stat->ready = true; $this->workersStat[$this->childPid] = $stat; */ // Wait for SIGUSR2 while (!$this->ready) { $this->sleepMillis(10); } } $this->worker->startChild(); if ($this->workQueue) { $memoryTick = new Scalr_Util_Timeout($this->workerMemoryLimitTick); $os = Scalr_System_OS::getInstance(); while ($message = $this->workQueue->peek()) { $t1 = microtime(true); $this->logger->info("Peek message from work queue"); // Notify parent before message handler /* $stat = $this->workersStat[$this->childPid]; $stat->message = $message; $stat->workStartTime = microtime(true); $stat->workEndTime = null; $this->workersStat[$this->childPid] = $stat; */ $this->fireChildEvent("beforeHandleWork", array("microtime" => microtime(true), "message" => $message)); //$this->timeLogger->info("before handle work ($message);; " . (microtime(true) - $t1) . ";;"); //$t1 = microtime(true); $this->worker->handleWork($message); //$this->timeLogger->info("handle work ($message);;; " . (microtime(true) - $t1) . ";"); //$t1 = microtime(true); // Notify parent after message handler $this->fireChildEvent("afterHandleWork", array("message" => $message)); if ($this->workerMemoryLimit && $memoryTick->reached(false)) { $this->fireChildEvent("memoryUsage", array("memory" => $os->getMemoryUsage(posix_getpid(), Scalr_System_OS::MEM_RES))); $memoryTick->reset(); } /* $stat = $this->workersStat[$this->childPid]; $stat->workEndTime = microtime(true); if ($this->workerMemoryLimit && $memoryTick->reached(false)) { $stat->memoryUsage = $os->getMemoryUsage($this->childPid, Scalr_System_OS::MEM_RES); $stat->memoryUsageTime = microtime(true); $memoryTick->reset(); } $this->workersStat[$this->childPid] = $stat; */ //$this->timeLogger->info("after handle work ($message);;;; " . (microtime(true) - $t1)); //$this->logger->info("TIME after handleWork : " . round(microtime(true) - $t1, 4) . " sec"); } } $this->worker->endChild(); $this->logger->info("Done"); } catch (Exception $e) { // Raise fatal error $this->logger->info(sprintf("Unhandled exception in worker process: <%s> '%s'", get_class($e), $e->getMessage())); $this->logger->info(sprintf("Worker process %d terminated (exit code: %d)", $this->childPid, self::$termExitCode)); // Sometimes (in our tests when daemonize=true) parent process doesn't receive SIGCHLD // Sending kill signal will force SIGCHLD // TODO: Consider it deeper posix_kill($this->childPid, SIGKILL); exit(self::$termExitCode); } exit; } } }
protected function checkMemoryLimit() { if ($this->config["memoryLimit"] && $this->memoryLimitTimeout->reached(false)) { $this->memoryLimitTimeout->reset(); // Check allocated memory $os = Scalr_System_OS::getInstance(); $this->logger->debug("Get process childs"); $gpids = $os->getProcessChilds($this->processPool->getPid()); // Get resident memory size for each process in group $memory = 0; foreach ($gpids as $pid) { $memory += $os->getMemoryUsage($pid, Scalr_System_OS::MEM_RES); } $memory += $os->getMemoryUsage(posix_getpid(), Scalr_System_OS::MEM_RES); $this->logger->debug("Memory usage: {$memory} Kb. Memory limit: {$this->config["memoryLimit"]} Kb"); if ($memory > $this->config["memoryLimit"]) { $this->logger->warn(sprintf("Cronjob allocates %d Kb. Maximum %d Kb is allowed by configuration", $memory, $this->config["memoryLimit"])); // Terminate cronjob posix_kill(posix_getpid(), SIGTERM); return 0; } } return 1; }