public function run() { proc_nice(Daemon::$settings['masterpriority']); gc_enable(); register_shutdown_function(array($this, 'onShutdown')); $this->collections = array('workers' => new threadCollection()); Thread::setproctitle(Daemon::$runName . ': master process' . (Daemon::$settings['pidfile'] !== Daemon::$settings['defaultpidfile'] ? ' (' . Daemon::$settings['pidfile'] . ')' : '')); Daemon::$appResolver = (require Daemon::$settings['path']); Daemon::$appResolver->preloadPrivileged(); $this->spawnWorkers(min(Daemon::$settings['startworkers'], Daemon::$settings['maxworkers'])); $mpmLast = time(); $autoReloadLast = time(); while (TRUE) { pcntl_signal_dispatch(); $this->sigwait(1, 0); clearstatcache(); if (Daemon::$logpointerpath !== Daemon::parseStoragepath(Daemon::$settings['logstorage'])) { $this->sigusr1(); } $c = 1; if (time() > $mpmLast + Daemon::$parsedSettings['mpmdelay']) { $mpmLast = time(); ++$c; if ($c > 0xfffff) { $c = 0; } if ($c % 10 == 0) { $this->collections['workers']->removeTerminated(TRUE); gc_collect_cycles(); } else { $this->collections['workers']->removeTerminated(); } if (isset(Daemon::$settings['mpm']) && is_callable($c = Daemon::$settings['mpm'])) { call_user_func($c); } else { $state = Daemon::getStateOfWorkers($this); if ($state) { $n = max(min(Daemon::$settings['minspareworkers'] - $state['idle'], Daemon::$settings['maxworkers'] - $state['alive']), Daemon::$settings['minworkers'] - $state['alive']); if ($n > 0) { Daemon::log('Spawning ' . $n . ' worker(s).'); $this->spawnWorkers($n); } $n = min($state['idle'] - Daemon::$settings['maxspareworkers'], $state['alive'] - Daemon::$settings['minworkers']); if ($n > 0) { Daemon::log('Stopping ' . $n . ' worker(s).'); $this->stopWorkers($n); } } } } } }
public function run() { proc_nice(Daemon::$settings['workerpriority']); Daemon::$worker = $this; $this->microsleep = Daemon::$settings['microsleep']; $this->autoReloadLast = time(); $this->reloadDelay = Daemon::$parsedSettings['mpmdelay'] + 2; $this->setStatus(4); Thread::setproctitle(Daemon::$runName . ': worker process' . (Daemon::$settings['pidfile'] !== Daemon::$settings['defaultpidfile'] ? ' (' . Daemon::$settings['pidfile'] . ')' : '')); register_shutdown_function(array($this, 'shutdown')); if (Daemon::$settings['autogc'] > 0) { gc_enable(); } else { gc_disable(); } if (isset(Daemon::$settings['group'])) { $sg = posix_getgrnam(Daemon::$settings['group']); } if (isset(Daemon::$settings['user'])) { $su = posix_getpwnam(Daemon::$settings['user']); } if (Daemon::$settings['chroot'] !== '/') { if (posix_getuid() != 0) { Daemon::log('You must have the root privileges to change root.'); exit(0); } elseif (!chroot(Daemon::$settings['chroot'])) { Daemon::log('Couldn\'t change root to \'' . Daemon::$settings['chroot'] . '\'.'); exit(0); } } if (isset(Daemon::$settings['group'])) { if ($sg === FALSE) { Daemon::log('Couldn\'t change group to \'' . Daemon::$settings['group'] . '\'. You must replace config-variable \'group\' with existing group.'); exit(0); } elseif ($sg['gid'] != posix_getgid() && !posix_setgid($sg['gid'])) { Daemon::log('Couldn\'t change group to \'' . Daemon::$settings['group'] . "'. Error (" . ($errno = posix_get_last_error()) . '): ' . posix_strerror($errno)); exit(0); } } if (isset(Daemon::$settings['user'])) { if ($su === FALSE) { Daemon::log('Couldn\'t change user to \'' . Daemon::$settings['user'] . '\', user not found. You must replace config-variable \'user\' with existing username.'); exit(0); } elseif ($su['uid'] != posix_getuid() && !posix_setuid($su['uid'])) { Daemon::log('Couldn\'t change user to \'' . Daemon::$settings['user'] . "'. Error (" . ($errno = posix_get_last_error()) . '): ' . posix_strerror($errno)); exit(0); } } if (Daemon::$settings['cwd'] !== '.') { if (!@chdir(Daemon::$settings['cwd'])) { Daemon::log('WORKER ' . $this->pid . '] Couldn\'t change directory to \'' . Daemon::$settings['cwd'] . '.'); } } $this->setStatus(6); $this->eventBase = event_base_new(); Daemon::$appResolver->preload(); foreach (Daemon::$appInstances as $app) { foreach ($app as $appInstance) { if (!$appInstance->ready) { $this->ready = TRUE; $appInstance->onReady(); } } } $this->setStatus(1); $ev = event_new(); event_set($ev, STDIN, EV_TIMEOUT, function () { }, array()); event_base_set($ev, $this->eventBase); $this->timeoutEvent = $ev; while (TRUE) { pcntl_signal_dispatch(); if (($s = $this->checkState()) !== TRUE) { $this->closeSockets(); if (sizeof($this->queue) === 0) { return $s; } } event_add($this->timeoutEvent, $this->microsleep); event_base_loop($this->eventBase, EVLOOP_ONCE); do { for ($i = 0, $s = sizeof($this->eventsToAdd); $i < $s; ++$i) { event_add($this->eventsToAdd[$i]); unset($this->eventsToAdd[$i]); } $this->readPool(); $processed = $this->runQueue(); } while ($processed || $this->readPoolState || $this->eventsToAdd); } }