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);
     }
 }