/** * Constructor. * * @param Master $master The master object * @param integer $pid The child process id or null if this is the child * * @throws \Exception * @throws \RuntimeException */ public function __construct(Master $master, $pid = null) { $this->master = $master; $directions = array('up', 'down'); if (null === $pid) { // child $pid = posix_getpid(); $pPid = posix_getppid(); $modes = array('write', 'read'); } else { // parent $pPid = null; $modes = array('read', 'write'); } $this->pid = $pid; $this->ppid = $pPid; foreach (array_combine($directions, $modes) as $direction => $mode) { $fifo = $this->getPath($direction); if (!file_exists($fifo) && !posix_mkfifo($fifo, 0600) && 17 !== ($error = posix_get_last_error())) { throw new \Exception(sprintf('Error while creating FIFO: %s (%d)', posix_strerror($error), $error)); } $this->{$mode} = fopen($fifo, $mode[0]); if (false === ($this->{$mode} = fopen($fifo, $mode[0]))) { throw new \RuntimeException(sprintf('Unable to open %s FIFO.', $mode)); } } }
/** * 进程启动 */ public function start() { // 安装信号处理函数 $this->installSignal(); // 添加accept事件 $ret = $this->event->add($this->mainSocket, Man\Core\Events\BaseEvent::EV_READ, array($this, 'accept')); // 创建内部通信套接字 $start_port = Man\Core\Lib\Config::get($this->workerName . '.lan_port_start'); $this->lanPort = $start_port - posix_getppid() + posix_getpid(); $this->lanIp = Man\Core\Lib\Config::get($this->workerName . '.lan_ip'); if (!$this->lanIp) { $this->notice($this->workerName . '.lan_ip not set'); $this->lanIp = '127.0.0.1'; } $error_no = 0; $error_msg = ''; $this->innerMainSocket = stream_socket_server("udp://" . $this->lanIp . ':' . $this->lanPort, $error_no, $error_msg, STREAM_SERVER_BIND); if (!$this->innerMainSocket) { $this->notice('create innerMainSocket fail and exit ' . $error_no . ':' . $error_msg); sleep(1); exit(0); } else { stream_set_blocking($this->innerMainSocket, 0); } $this->registerAddress("udp://" . $this->lanIp . ':' . $this->lanPort); // 添加读udp事件 $this->event->add($this->innerMainSocket, Man\Core\Events\BaseEvent::EV_READ, array($this, 'recvUdp')); // 初始化到worker的通信地址 $this->initWorkerAddresses(); // 主体循环,整个子进程会阻塞在这个函数上 $ret = $this->event->loop(); $this->notice('worker loop exit'); exit(0); }
public static function init() { self::$pid = \posix_getpid(); self::$ppid = \posix_getppid(); self::$child = array(); self::$alias = array(); self::$user_events = array(); self::$shm_to_pid = array(); self::$status['start_time'] = time(); // self::$shm_to_parent = -1; if (!self::$do_once) { // 初始化事件对象 if (extension_loaded('libevent')) { self::$events = new Libevent(); } else { self::$events = new Select(); } self::$shm = new Shm(__FILE__, 'a'); // 注册用户信号SIGUSR1处理函数 self::onSysEvent(SIGUSR1, EventInterface::EV_SIGNAL, array("\\cli\\proc\\Process", 'defaultSigusr1Cbk')); // 注册子进程退出处理函数 self::onSysEvent(SIGCHLD, EventInterface::EV_SIGNAL, array("\\cli\\proc\\Process", 'defaultSigchldCbk')); // 注册用户信号SIGUSR2处理函数 self::onSysEvent(SIGUSR2, EventInterface::EV_SIGNAL, array("\\cli\\proc\\Process", 'defaultSigusr2Cbk')); // 注册exit回调函数 register_shutdown_function(function () { Process::closeShm(); }); self::$do_once = true; } }
/** * Constructor. * * @param resource $fileStream File stream * @param string $messageTemplate Message template. * @param array $replacements Replacements for template */ public function __construct($fileStream, $messageTemplate = null, array $replacements = []) { if (empty($replacements)) { $replacements = array('{date}' => date('Y-m-d H:i:s'), '{message}' => null, '{pid}' => posix_getpid(), '{ppid}' => posix_getppid()); } $this->messageTemplate = $messageTemplate; $this->fileStream = $fileStream; $this->replacements = $replacements; }
private function checkExit() { $ppid = posix_getppid(); if ($this->ppid == 0) { $this->ppid = $ppid; } if ($this->ppid != $ppid) { $this->_exit(); } }
/** * завершение работы */ public function shutdown() { try { $this->onShutdown(); static::log(getmypid() . ' is getting shutdown', Logger::L_DEBUG); static::log('Parent PID - ' . posix_getppid(), Logger::L_TRACE); parent::shutdown(); } catch (\Exception $e) { exit(1); } }
public final function stillWorking() { if (!posix_isatty(STDOUT)) { posix_kill(posix_getppid(), SIGUSR1); } if ($this->traceMemory) { $memuse = number_format(memory_get_usage() / 1024, 1); $daemon = get_class($this); fprintf(STDERR, '%s', "<RAMS> {$daemon} Memory Usage: {$memuse} KB\n"); } }
function testSiteSet() { if ($this->is_windows()) { $this->markTestSkipped('Site-set not currently available on Windows.'); } $tmp_path = UNISH_TMP; putenv("TMPDIR={$tmp_path}"); $posix_pid = posix_getppid(); $expected_file = UNISH_TMP . '/drush-env/drush-drupal-site-' . $posix_pid; $filename = drush_sitealias_get_envar_filename(); $this->assertEquals($expected_file, $filename); }
protected function waitChild() { if (!$this->pid) { $file = sys_get_temp_dir() . '/parallel' . posix_getppid() . '.sock'; $address = 'unix://' . $file; $result = $this->run(); if ($client = stream_socket_client($address)) { stream_socket_sendto($client, serialize([posix_getpid(), $result])); fclose($client); } posix_kill(posix_getpid(), SIGHUP); return; } }
/** * * @return Comos\Qpm\Process\Process returns null on failure * It cannot be realtime in some cases. * e.g. * $child = Process::current()->folkByCallable($fun); * echo $child->getParent()->getPid(); * If child process changed the parent, you would get the old parent ID. */ public function getParent() { if ($this->_parentProcessId) { return self::process($this->_parentProcessId); } if ($this->isCurrent()) { $ppid = \posix_getppid(); if (!$ppid) { return null; } return self::process($ppid); } return null; }
/** * Constructor. * * @param integer $pid The child process id or null if this is the child * @param integer $signal The signal to send after writing to shared memory */ public function __construct($pid = null, $signal = null) { if (null === $pid) { // child $pid = posix_getpid(); $ppid = posix_getppid(); } else { // parent $ppid = null; } $this->pid = $pid; $this->ppid = $ppid; $this->signal = $signal; }
public static function buildProd($dump = null) { $dump = $dump ?: rtrim(sys_get_temp_dir(), "/") . "/" . posix_getppid(); $storage = CodeStorage::create($dump); if (extension_loaded("apc")) { $cache = new ApcCache("Spot"); } else { if (extension_loaded("xcache")) { $cache = new XcacheCache(); } else { $cache = new PhpFileCache($dump); } } return new Spot(Spot::PROD_MODE, $dump, $cache, $storage); }
function fork() { $pid = pcntl_fork(); if ($pid == -1) { throw new Exception('fork error on Task object'); } elseif ($pid) { // we are in the parent class $this->pid = $pid; // echo "< in parent with pid {$this->pid}\n"; } else { // we are in the child ᶘ ᵒᴥᵒᶅ $this->ppid = posix_getppid(); $this->pid = posix_getpid(); $this->run(); exit(0); } }
public function init() { $pid = pcntl_fork(); if ($pid == -1) { //Return message for the //echo json_encode(array('ERROR' => 1, 'MESSAGE' => 'CANNOT FORK, check php configuration', 'CODE_ERROR' => ERROR_FORK)); exit(1); } elseif ($pid) { //echo json_encode(array('PID' => $pid, 'ERROR' => 0, 'MESSAGE' => 'Running tasks...', 'PROGRESS' => 0)); exit(0); } else { //Daemonize the element $this->father_pid = posix_getppid(); $sid = posix_setsid(); $this->pid = getmypid(); echo $this->father_pid; $this->log(array('ERROR' => 0, 'MESSAGE' => 'Running daemon...', 'PROGRESS' => 0)); } }
public function forkChild($callback, $data) { $pid = pcntl_fork(); switch ($pid) { case 0: // Child process $this->isChild = true; call_user_func_array($callback, $data); posix_kill(posix_getppid(), SIGCHLD); exit; case -1: // Parent process, fork failed throw new \Exception("Out of memory!"); default: // Parent process, fork succeeded $this->processes[$pid] = true; return $pid; } }
function check_files_change($monitor_dir) { // 递归遍历目录 $dir_iterator = new RecursiveDirectoryIterator($monitor_dir); $iterator = new RecursiveIteratorIterator($dir_iterator); $time_now = time(); foreach ($iterator as $file) { // 只监控php文件 if (pathinfo($file, PATHINFO_EXTENSION) != 'php') { continue; } // 在最近1秒内有修改 if ($time_now - $file->getMTime() == 1) { echo $file . " update and reload\n"; // 给父进程发送reload信号 posix_kill(posix_getppid(), SIGUSR1); } } }
function check_files_change($inotify_fd) { global $monitor_files; // 读取有哪些文件事件 $events = inotify_read($inotify_fd); if ($events) { // 检查哪些文件被更新了 foreach ($events as $ev) { // 更新的文件 $file = $monitor_files[$ev['wd']]; echo $file . " update and reload\n"; unset($monitor_files[$ev['wd']]); // 需要把文件重新加入监控 $wd = inotify_add_watch($inotify_fd, $file, IN_MODIFY); $monitor_files[$wd] = $file; } // 给父进程也就是主进程发送reload信号 posix_kill(posix_getppid(), SIGUSR1); } }
function run($work) { if (1 === posix_getppid()) { return; } if ($this->user) { if (!posix_setgid($this->user['gid']) || !posix_setuid($this->user['uid'])) { throw new \RuntimeException("Unable to switch to user '{$this->user['name']}'"); } } Utility::fork(function () use($work) { if (-1 === posix_setsid()) { throw new \RuntimeException('Unable to set setsid()'); } if (false === chdir('/')) { throw new \RuntimeException('Unable to chdir(\'/\')'); } umask(0); Utility::fork($work); }); }
public static function kill() { $rets = $match = array(); $process_lists = [isset(self::$serverConfig['server']['master_process_name']) ? self::$serverConfig['server']['master_process_name'] : 'ypf:swoole-master', isset(self::$serverConfig['server']['worker_process_name']) ? self::$serverConfig['server']['worker_process_name'] : 'ypf:swoole-worker-%d', isset(self::$serverConfig['server']['task_worker_process_name']) ? self::$serverConfig['server']['task_worker_process_name'] : 'ypf:swoole-task-worker-%d', isset(self::$serverConfig['server']['cron_worker_process_name']) ? self::$serverConfig['server']['cron_worker_process_name'] : 'ypf:swoole-cron-worker']; foreach ($process_lists as $i => $process_name) { $process_name = str_replace("%d", "", $process_name); exec("ps aux | grep -E '" . $process_name . "' | grep -v grep", $rets[$i]); } $this_pid = posix_getpid(); $this_ppid = posix_getppid(); foreach ($rets as $ret) { foreach ($ret as $line) { if (preg_match("/^[\\S]+\\s+(\\d+)\\s+/", $line, $match)) { $tmp_pid = $match[1]; if ($this_pid != $tmp_pid && $this_ppid != $tmp_pid) { posix_kill($tmp_pid, 9); } } } } exit("server killed ..." . PHP_EOL); }
/** * @param string $instance * @return void */ public function forked(string $instance = 'child') { $this->pid = posix_getpid(); $this->parentPid = posix_getppid(); $this->setInstanceName($instance); }
<?php declare (ticks=1); define('SCALR_MULTITHREADING', true); define("NO_TEMPLATES", true); define("NO_SESSIONS", true); require_once __DIR__ . "/../src/prepend.inc.php"; $Logger = \Scalr::getContainer()->logger('Application'); $fname = basename($argv[0]); $JobLauncher = new \Scalr\System\Pcntl\JobLauncher(dirname(__FILE__)); // DBQueueEvent - it is a daemon process so we must skeep this check if ($JobLauncher->GetProcessName() != 'DBQueueEvent') { $Shell = new Scalr_System_Shell(); // Set terminal width putenv("COLUMNS=200"); // Execute command $parent_pid = posix_getppid(); $ps = $Shell->queryRaw("ps x -o pid,command | grep -v -E '^ *(" . $parent_pid . "|" . posix_getpid() . ") | ps x' | grep '" . dirname(__FILE__) . "' | egrep '\\-\\-{$JobLauncher->GetProcessName()}\$'"); if ($ps) { $Logger->info("'{$fname} --{$JobLauncher->GetProcessName()}' already running. Exiting."); exit; } } $Logger->info(sprintf("Starting %s cronjob...", $JobLauncher->GetProcessName())); $JobLauncher->Launch(7, 180);
/** * 当Gateway启动的时候触发的回调函数 * @return void */ public function onWorkerStart() { // 分配一个内部通讯端口 $this->lanPort = function_exists('posix_getppid') ? $this->startPort - posix_getppid() + posix_getpid() : $this->startPort; if ($this->lanPort < 0 || $this->lanPort >= 65535) { $this->lanPort = rand($this->startPort, 65535); } // 如果有设置心跳,则定时执行 if ($this->pingInterval > 0) { $timer_interval = $this->pingNotResponseLimit > 0 ? $this->pingInterval / 2 : $this->pingInterval; Timer::add($timer_interval, array($this, 'ping')); } if (!class_exists('\\Protocols\\GatewayProtocol')) { class_alias('\\GatewayWorker\\Protocols\\GatewayProtocol', 'Protocols\\GatewayProtocol'); } // 初始化gateway内部的监听,用于监听worker的连接已经连接上发来的数据 $this->_innerTcpWorker = new Worker("GatewayProtocol://{$this->lanIp}:{$this->lanPort}"); $this->_innerTcpWorker->listen(); $this->_innerUdpWorker = new Worker("GatewayProtocol://{$this->lanIp}:{$this->lanPort}"); $this->_innerUdpWorker->transport = 'udp'; $this->_innerUdpWorker->listen(); // 重新设置自动加载根目录 Autoloader::setRootPath($this->_appInitPath); // 设置内部监听的相关回调 $this->_innerTcpWorker->onMessage = array($this, 'onWorkerMessage'); $this->_innerUdpWorker->onMessage = array($this, 'onWorkerMessage'); $this->_innerTcpWorker->onConnect = array($this, 'onWorkerConnect'); $this->_innerTcpWorker->onClose = array($this, 'onWorkerClose'); // 注册gateway的内部通讯地址,worker去连这个地址,以便gateway与worker之间建立起TCP长连接 if (!$this->registerAddress()) { $this->log('registerAddress fail and exit'); Worker::stopAll(); } if ($this->_onWorkerStart) { call_user_func($this->_onWorkerStart, $this); } }
/** * 向shell输出一条消息 * * @param string $message */ private static function message($message = '') { printf(PHP_EOL . "%s %d %d %s" . PHP_EOL, date('Y-m-d H:i:s'), posix_getpid(), posix_getppid(), $message); }
VERIFY($ret != false); VERIFY(count((array) $ret) != 0); $bynam = posix_getgrnam($ret['name']); VS($ret, $bynam); $ret = posix_getgrnam("root"); VERIFY($ret != false); VERIFY(count((array) $ret) != 0); $bygid = posix_getgrgid($ret['gid']); VS($ret, $bygid); // $ret = posix_getgroups(); // VERIFY($ret != false); // VERIFY(count((array)$ret) != 0); VERIFY(posix_getpgid(0)); VERIFY(posix_getpgrp()); VERIFY(posix_getpid()); VERIFY(posix_getppid()); $ret = posix_getpwnam("root"); VERIFY($ret != false); VERIFY(count((array) $ret) != 0); VS(posix_getpwnam(""), false); VS(posix_getpwnam(-1), false); $ret = posix_getpwuid(0); VERIFY($ret != false); VERIFY(count((array) $ret) != 0); VS(posix_getpwuid(-1), false); $ret = posix_getrlimit(); VERIFY($ret != false); VERIFY(count((array) $ret) != 0); VERIFY(posix_getsid(posix_getpid())); $tmpfifo = tempnam('/tmp', 'vmmkfifotest'); unlink($tmpfifo);
$pid = pcntl_fork(); if ($pid < 0) { error_log("unable to fork daemon"); $script->shutdown(1, "unable to fork daemon"); } // If we got a good PID, then we can wait until the daemon tells us to terminate if ($pid > 0) { // Wait for confirmation from the child via SIGTERM or SIGCHLD, or // for two seconds to elapse (SIGALRM). pause() should not return. */ sleep(10); $script->shutdown(1, "Failed spawning the daemon process"); } $pidFp = fopen($pidFile, 'w'); flock($pidFp, LOCK_EX | LOCK_NB); // At this point we are executing as the child process $parentProcessID = posix_getppid(); /* Cancel certain signals */ pcntl_signal(SIGCHLD, SIG_DFL); // A child process dies pcntl_signal(SIGTSTP, SIG_IGN); // Various TTY signals pcntl_signal(SIGTTOU, SIG_IGN); pcntl_signal(SIGTTIN, SIG_IGN); pcntl_signal(SIGHUP, SIG_IGN); // Ignore hangup signal $sid = posix_setsid(); if ($sid < 0) { error_log("unable to create a new session"); $script->shutdown(1, 'unable to create a new session'); } pcntl_signal(SIGTERM, $daemonSignalHandler);
/** * Sends the signal to parent process * @param integer Signal's number * @return void */ private function backsig($sig) { return posix_kill(posix_getppid(), $sig); }
/** * @param bool $fork * @param bool $restart * @throws Exception */ public function runProcess($fork = true, $restart = false) { $pidFile = $this->getProcess()->getPidFile(); $lockFile = $this->getProcess()->getLockFile(); if (is_file($pidFile) && is_writable($pidFile)) { unlink($pidFile); } if (is_file($lockFile) && is_writable($lockFile)) { unlink($lockFile); } $this->changeUser(); if ($fork) { $pid = pcntl_fork(); } if (!$fork || isset($pid) && $pid !== -1 && !$pid) { $this->getProcess()->setPid(posix_getpid()); if (isset($pid) && $pid !== -1 && !$pid) { $parentPid = posix_getppid(); if ($parentPid) { posix_kill(posix_getppid(), SIGUSR2); } } $this->lock = $this->getProcess()->lock(); if (null !== $this->logger) { $this->logger->info("Started GearmanWorker Server"); } $this->signalHandlers(); $this->createLoop($restart); } elseif ($fork && isset($pid) && $pid) { $wait = true; pcntl_signal(SIGUSR2, function () use(&$wait) { $wait = false; }); while ($wait) { pcntl_waitpid($pid, $status, WNOHANG); pcntl_signal_dispatch(); } } }
/** * display info * * @return */ public function _log($line, $flag = true) { if ($flag) { printf("%s\t%d\t%d\t%s\n", date('Y-m-d H:i:s'), posix_getpid(), posix_getppid(), $line); } else { printf("\n%s\n", $line); } }
public function shutdown($hard = FALSE) { if (Daemon::$settings['logevents']) { Daemon::log('[WORKER ' . $this->pid . '] event shutdown(' . ($hard ? 'HARD' : '') . ') invoked.'); } if (Daemon::$settings['throwexceptiononshutdown']) { throw new Exception('event shutdown'); } @ob_flush(); if ($this->terminated === TRUE) { if ($hard) { exit(0); } return; } $this->terminated = TRUE; $this->closeSockets(); $this->setStatus(3); if ($hard) { exit(0); } $reloadReady = $this->appInstancesReloadReady(); foreach ($this->queue as $r) { if ($r instanceof stdClass) { continue; } if ($r->running) { $r->finish(-2); } } $n = 0; while ($this->queueWait && sizeof($this->queue) > 0 || !$reloadReady) { if ($n++ === 100) { $reloadReady = $this->appInstancesReloadReady(); $n = 0; } pcntl_signal_dispatch(); event_add($this->timeoutEvent, $this->microsleep); event_base_loop($this->eventBase, EVLOOP_ONCE); $this->readPool(); $this->runQueue(); } posix_kill(posix_getppid(), SIGCHLD); exit(0); }
/** * 进程启动 */ public function start() { // 安装信号处理函数 $this->installSignal(); // 添加accept事件 $ret = $this->event->add($this->mainSocket, Man\Core\Events\BaseEvent::EV_READ, array($this, 'accept')); // 创建内部通信套接字,用于与BusinessWorker通讯 $start_port = Man\Core\Lib\Config::get($this->workerName . '.lan_port_start'); // 计算本进程监听的ip端口 if (strpos(\Man\Core\Master::VERSION, 'mt')) { $this->lanPort = $start_port + \Thread::getCurrentThreadId() % 100; } else { $this->lanPort = $start_port - posix_getppid() + posix_getpid(); } // 如果端口不在合法范围 if ($this->lanPort < 0 || $this->lanPort >= 65535) { $this->lanPort = rand($start_port, 65535); } // 如果 $this->lanIp = Man\Core\Lib\Config::get($this->workerName . '.lan_ip'); if (!$this->lanIp) { $this->notice($this->workerName . '.lan_ip not set'); $this->lanIp = '127.0.0.1'; } $error_no_udp = $error_no_tcp = 0; $error_msg_udp = $error_msg_tcp = ''; // 执行监听 $this->innerMainSocketUdp = stream_socket_server("udp://" . $this->lanIp . ':' . $this->lanPort, $error_no_udp, $error_msg_udp, STREAM_SERVER_BIND); $this->innerMainSocketTcp = stream_socket_server("tcp://" . $this->lanIp . ':' . $this->lanPort, $error_no_tcp, $error_msg_tcp, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN); // 出错,退出,下次会换个端口 if (!$this->innerMainSocketUdp || !$this->innerMainSocketTcp) { $this->notice('create innerMainSocket udp or tcp fail and exit ' . $error_msg_udp . $error_msg_tcp); $this->stop(); } else { stream_set_blocking($this->innerMainSocketUdp, 0); stream_set_blocking($this->innerMainSocketTcp, 0); } // 注册套接字 if (!$this->registerAddress($this->lanIp . ':' . $this->lanPort)) { $this->notice('registerAddress fail and exit'); $this->stop(); } // 添加读udp/tcp事件 $this->event->add($this->innerMainSocketUdp, Man\Core\Events\BaseEvent::EV_READ, array($this, 'recvInnerUdp')); $this->event->add($this->innerMainSocketTcp, Man\Core\Events\BaseEvent::EV_READ, array($this, 'acceptInnerTcp')); // 初始化心跳包时间间隔 $ping_interval = \Man\Core\Lib\Config::get($this->workerName . '.ping_interval'); if ((int) $ping_interval > 0) { $this->pingInterval = (int) $ping_interval; } // 获取心跳包数据 $ping_data_or_path = \Man\Core\Lib\Config::get($this->workerName . '.ping_data'); if (is_file($ping_data_or_path)) { $this->pingData = file_get_contents($ping_data_or_path); } else { $this->pingData = $ping_data_or_path; } // 不返回心跳回应(客户端发来的任何数据都算是回应)的限定值 $this->pingNotResponseLimit = (int) \Man\Core\Lib\Config::get($this->workerName . '.ping_not_response_limit'); // 设置定时任务,发送心跳 if ($this->pingInterval > 0) { \Man\Core\Lib\Task::init($this->event); \Man\Core\Lib\Task::add($this->pingInterval, array($this, 'ping')); } // 主体循环,整个子进程会阻塞在这个函数上 $ret = $this->event->loop(); // 下面正常不会执行到 $this->notice('worker loop exit'); // 执行到就退出 exit(0); }