/** * 运行守护进程,监控有变化的日志文件。 * * @see ZtChart_Model_Monitor_Abstract::daemon() */ public function run() { if (0 == ($pid = pcntl_fork())) { // 子进程负责处理当前日志 try { $this->tail($this->_console->getLogPaths()); } catch (ZtChart_Model_Monitor_Exception $e) { $this->_logger->err($e->getMessage()); exit(1); } } else { if (0 < $pid) { pcntl_setpriority(-1); // 父进程负责把子进产生的数据写入数据库 if (pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD, SIGALRM, SIGINT, SIGTERM))) { $interval = 10; // 10秒写一次 pcntl_alarm($interval); while ($signo = pcntl_sigwaitinfo(array(SIGCHLD, SIGALRM, SIGINT, SIGTERM))) { if (SIGALRM == $signo) { pcntl_alarm($interval); } try { $this->extract($interval); } catch (ZtChart_Model_Monitor_Exception $e) { posix_kill($pid, 9); exit(1); } if (SIGCHLD == $signo || SIGINT == $signo || SIGTERM == $signo) { break; } } } } } exit(0); }
/** * Set Priority * * @param int $priority Generally a value in the range -20 to 20. The default priority is 0 while a lower numerical value causes more favorable scheduling. * @param int $pid If not specified, the pid of the current process is used. * @param int $processIdentifier One of PRIO_PGRP, PRIO_USER or PRIO_PROCESS. * * @return bool TRUE on success or FALSE on failure. */ public function setPriority($priority, $pid = null, $processIdentifier = PRIO_PROCESS) { return pcntl_setpriority($priority, $pid, $processIdentifier); }
/** * Устанавливает приоритет для дочерних процессов * * @param integer $iWorkerPriority * @return boolean */ private function setPriority($iWorkerPriority) { return $iWorkerPriority ? pcntl_setpriority($iWorkerPriority) : false; }
/** * テーブルの未使用領域を解放し、データファイルを最適化します。 * MySQLController::optimizeTable() を実行するには、MySQL のプロセスがあらかじめ終了している必要があります。 * * @author Naomichi Yamakita <*****@*****.**> * @see http://dev.mysql.com/doc/refman/4.1/ja/optimisation.html */ public function optimizeTable() { // MySQLController::checkTable() で統計を更新するため、ここでは OPTIMIZE TABLE を使用しない $command = sprintf('%s/bin/myisamchk -r %s/%s/', self::MYSQL_ROOT_DIR, self::MYSQL_DATA_DIR, $dbName); // "Deleted blocks" がおおよそ 100000 以上となるテーブルを対象とする $optimizeTables = Mars_Config::loadProperties('database.optimizeTables'); pcntl_setpriority(20); foreach ($optimizeTables as $table) { $start = microtime(TRUE); shell_exec(sprintf('%s%s.MYI', $command, $table)); $second = microtime(TRUE) - $start; file_put_contents('/home/mysql/isambench', sprintf("%s:%s\n", $table, $second), FILE_APPEND); } }
function start($multiProcess) { $t1 = microtime(true); $msg = "Starting process pool (size: {$this->size}"; if ($this->daemonize) { $msg .= ", daemonize: true"; } $msg .= ")"; $this->logger->info($msg); // @see http://www.php.net/manual/en/function.pcntl-fork.php#41150 @ob_end_flush(); if ($this->daemonize) { $this->logger->info("Going to daemonize process pool. Fork child process"); $pid = pcntl_fork(); if ($pid == -1) { throw new Scalr_System_Ipc_Exception("Cannot daemonize process pool: cannot fork process"); } else { if ($pid == 0) { // Child $this->logger->info("Detaching process from terminal"); if (posix_setsid() == -1) { throw new Scalr_System_Ipc_Exception("Cannot detach process from terminal"); } $this->sleepMillis(200); } else { // Parent process die; } } } $this->poolPid = posix_getpid(); $multiProcess->onReady($this); $this->initSignalHandler(); /* $this->workersStat = new Scalr_System_Ipc_ShmArray(array( "name" => "scalr.ipc.processPool.workersStat.{$this->poolPid}" )); */ $this->shm->put(self::SHM_STARTUP_BARRIER, 0); $this->childEventQueue = new Scalr_System_Ipc_ShmQueue(array("name" => "scalr.ipc.processPool.ev-" . $this->poolPid, "autoInit" => true)); $this->timeoutFly = new Scalr_Util_Timeout(0); // Start forking try { $userWorkQueue = $this->worker->startForking($this->workQueue); if ($userWorkQueue) { $this->workQueue = $userWorkQueue; } } catch (Exception $e) { $this->logger->error("Exception in worker->startForking(). " . "Caught: <" . get_class($e) . "> {$e->getMessage()}"); $this->shutdown(); throw $e; } // Fork childs for ($i = 0; $i < $this->size; $i++) { try { $this->forkChild(); } catch (Exception $e) { $this->logger->error("Exception during fork childs. " . "Caught: <" . get_class($e) . "> {$e->getMessage()}"); $this->shutdown(); throw $e; } } // Wait when all childs enter startup barrier if (!pcntl_setpriority(-10)) { $this->logger->warn("Cannot set higher priority for main process"); } try { $timeout = new Scalr_Util_Timeout($this->startupTimeout); while (!$timeout->reached()) { //if (count($this->workersStat) == $this->size) { // break; //} $this->handleChildEvents(); $this->logger->info("Barrier capacity: " . $this->shm->get(self::SHM_STARTUP_BARRIER)); if ($this->shm->get(self::SHM_STARTUP_BARRIER) == $this->size) { break; } $timeout->sleep(10); } } catch (Scalr_Util_TimeoutException $e) { $this->logger->error("Caught timeout exception"); $this->shutdown(); throw new Scalr_System_Ipc_Exception(sprintf("Timeout exceed (%d millis) " . "while waiting when all childs enter startup barrier", $this->startupTimeout)); } $this->logger->debug("All children (" . count($this->childs) . ") have entered startup barrier"); //$this->timeLogger->info("startup;" . (microtime(true) - $t1) . ";;;"); // Send to all childs SIGUSR2 $this->logger->debug("Send SIGUSR2 to all workers"); foreach ($this->childs as $i => $childInfo) { $this->kill($childInfo["pid"], SIGUSR2); // Wakeup $this->childs[$i]["startTime"] = microtime(true); } $this->logger->debug("Process pool is ready"); $this->ready = true; $this->fireEvent("ready", $this); $this->wait(); }
/** * Change child process priority according to EXTENDER_NICENESS * */ private static function adjustNiceness($pid, $logger) { if (Checks::multithread() and defined("EXTENDER_CHILD_NICENESS")) { $niceness = pcntl_setpriority($pid, EXTENDER_CHILD_NICENESS); if ($niceness == false) { $logger->warning("Unable to set child process " . $pid . " niceness to " . EXTENDER_CHILD_NICENESS); } } }
/** * Get process priority * * @return void */ public function setPriority($priority) { pcntl_setpriority(intval($priority), posix_getpid()); }
/** * Fork a new process, optionally within the supplied process $group. * @param null $group * @return bool|Core_Lib_Process On failure, will return false. On success, a Core_Lib_Process object will be * returned to the caller in the original (parent) process, and True will be returned to the caller in the * new (child) process. */ public function fork($group = null) { $pid = pcntl_fork(); switch ($pid) { case -1: // Parent Process - Fork Failed return false; case 0: // Child Process @pcntl_setpriority(1); $this->daemon->dispatch(array(Core_Daemon::ON_FORK)); return true; default: // Parent Process - Return the pid of the newly created Task $proc = new Core_Lib_Process(); $proc->pid = $pid; $proc->group = $group; if (!isset($this->processes[$group])) { $this->processes[$group] = array(); } $this->processes[$group][$pid] = $proc; return $proc; } }
/** * Sets the fork's scheduling priority as a percentage. * * Note that on many systems, only the superuser can increase the priority of a process. * * @param float $priority A priority value between 0 and 1. * * @throws InvalidArgumentError If the given priority is an invalid value. * @throws ForkException If the operation failed. * * @see Fork::getPriority() */ public function setPriority(float $priority) : float { if ($priority < 0 || $priority > 1) { throw new InvalidArgumentError('Priority value must be between 0.0 and 1.0.'); } $nice = round(19 - $priority * 39); if (!pcntl_setpriority($nice, $this->pid, PRIO_PROCESS)) { throw new ForkException('Failed to set the fork\'s priority.'); } }
echo "Got signal from child1\n"; $firstChildIsFree = true; } elseif ($siginfo['signo'] == SIGUSR2) { echo "Got signal from child2\n"; $secondChildIsFree = true; } } sleep(1); } } else { pcntl_setpriority(5); echo "Child2 waiting for SIGHUP\n"; while (true) { pcntl_sigwaitinfo(array(SIGHUP)); echo "Child2 has been activated\n"; sleep(10); echo "Child2 is now free, notify parent #{$parentPid}\n"; posix_kill($parentPid, SIGUSR2); } } } else { pcntl_setpriority(5); echo "Child1 waiting for SIGHUP\n"; while (true) { pcntl_sigwaitinfo(array(SIGHUP)); echo "Child1 has been activated\n"; sleep(10); echo "Child1 is now free, notify parent #{$parentPid}\n"; posix_kill($parentPid, SIGUSR1); } }
// デーモン化 function daemon() { if (pcntl_fork() != 0) { exit; } posix_setsid(); if (pcntl_fork() != 0) { exit; } pcntl_signal(SIGTERM, "handler"); } // デーモン化 daemon(); // プライオリティ低に pcntl_setpriority(20); include_once 'config.php'; include_once INSTALL_PATH . '/DBRecord.class.php'; include_once INSTALL_PATH . '/Reservation.class.php'; include_once INSTALL_PATH . '/Keyword.class.php'; include_once INSTALL_PATH . '/Settings.class.php'; $settings = Settings::factory(); if (file_exists($file)) { storeProgram($type, $file); @unlink($file); } // 不要なプログラムの削除 // 8日以上前のプログラムを消す $arr = array(); $arr = DBRecord::createRecords(PROGRAM_TBL, "WHERE endtime < subdate( now(), 8 )"); foreach ($arr as $val) {
/** * For a single fork during the pull jobs. * Takes a lower priority and pulls a batch of items. * @param int $i The index number of this worker (for round-robin). * @param int $threadc The amount of workers (for round-robin). * @param array $pull_batch A batch of URL's to pull. * @param string $db_host DB host to connect to. * @param string $db_user DB user to connect with. * @param string $db_pass DB pass to connect with. * @param mixed $db_data Nobody knows. * @param mixed $install Maybe a boolean. * @return void */ function pull_worker($i, $threadc, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install) { //Lets be nice, we're only doing maintenance here... pcntl_setpriority(5); //Get personal DBA's. global $db; $db = new dba($db_host, $db_user, $db_pass, $db_data, $install); //Get our (round-robin) workload from the batch. $workload = array(); while (isset($pull_batch[$i])) { $entry = $pull_batch[$i]; $workload[] = $entry; $i += $threadc; } //While we've got work to do. while (count($workload)) { $entry = array_pop($workload); set_time_limit(20); //This should work for 1 submit. msg("Submitting " . $entry['url']); run_submit($entry['url']); } }
echo "Got: {$x}\n"; var_dump(debug_backtrace()); } } function VERIFY($x) { VS($x != false, true); } ////////////////////////////////////////////////////////////////////// $pid = pcntl_fork(); if ($pid == 0) { exit(123); } pcntl_wait($status); VS(pcntl_getpriority(), 0); VERIFY(pcntl_setpriority(0)); $pid = pcntl_fork(); if ($pid == 0) { exit(0x12); } pcntl_wait($status); VS($status, 0x1200); $pid = pcntl_fork(); if ($pid == 0) { exit(0x12); } pcntl_waitpid(0, $status); VS($status, 0x1200); $pid = pcntl_fork(); if ($pid == 0) { exit(0x80);
/** * Combination getter/setter for the $loop_interval property. * @param boolean $set_value * @return int|null */ protected function loop_interval($set_value = null) { if ($set_value === null) { return $this->loop_interval; } if (!is_numeric($set_value)) { throw new Exception(__METHOD__ . ' Failed. Could not set loop interval. Number Expected. Given: ' . $set_value); } $this->loop_interval = $set_value; $priority = -1; if ($set_value >= 5.0 || $set_value <= 0.0) { $priority = 0; } if ($priority == pcntl_getpriority()) { return; } @pcntl_setpriority($priority); if (pcntl_getpriority() == $priority) { $this->log('Adjusting Process Priority to ' . $priority); } else { $this->log("Warning: At configured loop_interval a process priorty of `{$priority}` is suggested but this process does not have setpriority privileges.\n" . " Consider running the daemon with `CAP_SYS_RESOURCE` privileges or set it manually using `sudo renice -n {$priority} -p {$this->pid}`"); } }
/** * Sets the execution priority of the thread. A super user privileges are required. * @param int $priority The priority number in the interval [-20; 20] where the lower value means higher priority. * @return bool Returns true on success otherwise returns false. */ public function setPriority($priority) { // {{{ super user privileges required if (!is_numeric($priority)) { return false; } if ($this->amIParent()) { // I am parent if ($this->amIStarted) { return @pcntl_setpriority($priority, $this->childPid, PRIO_PROCESS); } else { return false; } } return @pcntl_setpriority($priority, $this->_childPid, PRIO_PROCESS); // I am child }
/** * @param int $priority * * @return void * * @throws ProcessException If an error occurs. */ public function setPriority($priority) { if (!pcntl_setpriority($priority, $this->pid)) { throw ProcessException::setPriorityError(); } }