[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 abstract class PhabricatorAphlictManagementWorkflow 4 extends PhabricatorManagementWorkflow { 5 6 final public function getPIDPath() { 7 return PhabricatorEnv::getEnvConfig('notification.pidfile'); 8 } 9 10 final public function getPID() { 11 $pid = null; 12 if (Filesystem::pathExists($this->getPIDPath())) { 13 $pid = (int)Filesystem::readFile($this->getPIDPath()); 14 } 15 return $pid; 16 } 17 18 final public function cleanup($signo = '?') { 19 global $g_future; 20 if ($g_future) { 21 $g_future->resolveKill(); 22 $g_future = null; 23 } 24 25 Filesystem::remove($this->getPIDPath()); 26 27 exit(1); 28 } 29 30 public static function requireExtensions() { 31 self::mustHaveExtension('pcntl'); 32 self::mustHaveExtension('posix'); 33 } 34 35 private static function mustHaveExtension($ext) { 36 if (!extension_loaded($ext)) { 37 echo "ERROR: The PHP extension '{$ext}' is not installed. You must ". 38 "install it to run aphlict on this machine.\n"; 39 exit(1); 40 } 41 42 $extension = new ReflectionExtension($ext); 43 foreach ($extension->getFunctions() as $function) { 44 $function = $function->name; 45 if (!function_exists($function)) { 46 echo "ERROR: The PHP function {$function}() is disabled. You must ". 47 "enable it to run aphlict on this machine.\n"; 48 exit(1); 49 } 50 } 51 } 52 53 final protected function willLaunch() { 54 $console = PhutilConsole::getConsole(); 55 56 $pid = $this->getPID(); 57 if ($pid) { 58 throw new PhutilArgumentUsageException( 59 pht( 60 'Unable to start notifications server because it is already '. 61 'running. Use `aphlict restart` to restart it.')); 62 } 63 64 if (posix_getuid() != 0) { 65 throw new PhutilArgumentUsageException( 66 pht( 67 'You must run this script as root; the Aphlict server needs to bind '. 68 'to privileged ports.')); 69 } 70 71 // This will throw if we can't find an appropriate `node`. 72 $this->getNodeBinary(); 73 } 74 75 final protected function launch($debug = false) { 76 $console = PhutilConsole::getConsole(); 77 78 if ($debug) { 79 $console->writeOut(pht("Starting Aphlict server in foreground...\n")); 80 } else { 81 Filesystem::writeFile($this->getPIDPath(), getmypid()); 82 } 83 84 $server_uri = PhabricatorEnv::getEnvConfig('notification.server-uri'); 85 $server_uri = new PhutilURI($server_uri); 86 87 $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); 88 $client_uri = new PhutilURI($client_uri); 89 90 $user = PhabricatorEnv::getEnvConfig('notification.user'); 91 $log = PhabricatorEnv::getEnvConfig('notification.log'); 92 93 $server_argv = array(); 94 $server_argv[] = csprintf('--port=%s', $client_uri->getPort()); 95 $server_argv[] = csprintf('--admin=%s', $server_uri->getPort()); 96 $server_argv[] = csprintf('--host=%s', $server_uri->getDomain()); 97 98 if ($user) { 99 $server_argv[] = csprintf('--user=%s', $user); 100 } 101 102 if (!$debug) { 103 $server_argv[] = csprintf('--log=%s', $log); 104 } 105 106 $command = csprintf( 107 '%s %s %C', 108 $this->getNodeBinary(), 109 dirname(__FILE__).'/../../../../support/aphlict/server/aphlict_server.js', 110 implode(' ', $server_argv)); 111 112 if (!$debug) { 113 declare(ticks = 1); 114 pcntl_signal(SIGINT, array($this, 'cleanup')); 115 pcntl_signal(SIGTERM, array($this, 'cleanup')); 116 } 117 register_shutdown_function(array($this, 'cleanup')); 118 119 if ($debug) { 120 $console->writeOut("Launching server:\n\n $ ".$command."\n\n"); 121 122 $err = phutil_passthru('%C', $command); 123 $console->writeOut(">>> Server exited!\n"); 124 exit($err); 125 } else { 126 while (true) { 127 global $g_future; 128 $g_future = new ExecFuture('exec %C', $command); 129 $g_future->resolve(); 130 131 // If the server exited, wait a couple of seconds and restart it. 132 unset($g_future); 133 sleep(2); 134 } 135 } 136 } 137 138 139 /* -( Commands )----------------------------------------------------------- */ 140 141 142 final protected function executeStartCommand() { 143 $console = PhutilConsole::getConsole(); 144 $this->willLaunch(); 145 146 $pid = pcntl_fork(); 147 if ($pid < 0) { 148 throw new Exception('Failed to fork()!'); 149 } else if ($pid) { 150 $console->writeErr(pht("Aphlict Server started.\n")); 151 exit(0); 152 } 153 154 // When we fork, the child process will inherit its parent's set of open 155 // file descriptors. If the parent process of bin/aphlict is waiting for 156 // bin/aphlict's file descriptors to close, it will be stuck waiting on 157 // the daemonized process. (This happens if e.g. bin/aphlict is started 158 // in another script using passthru().) 159 fclose(STDOUT); 160 fclose(STDERR); 161 162 $this->launch(); 163 return 0; 164 } 165 166 167 final protected function executeStopCommand() { 168 $console = PhutilConsole::getConsole(); 169 170 $pid = $this->getPID(); 171 if (!$pid) { 172 $console->writeErr(pht("Aphlict is not running.\n")); 173 return 0; 174 } 175 176 $console->writeErr(pht("Stopping Aphlict Server (%s)...\n", $pid)); 177 posix_kill($pid, SIGINT); 178 179 $start = time(); 180 do { 181 if (!PhabricatorDaemonReference::isProcessRunning($pid)) { 182 $console->writeOut( 183 "%s\n", 184 pht('Aphlict Server (%s) exited normally.', $pid)); 185 $pid = null; 186 break; 187 } 188 usleep(100000); 189 } while (time() < $start + 5); 190 191 if ($pid) { 192 $console->writeErr(pht('Sending %s a SIGKILL.', $pid)."\n"); 193 posix_kill($pid, SIGKILL); 194 unset($pid); 195 } 196 197 Filesystem::remove($this->getPIDPath()); 198 return 0; 199 } 200 201 private function getNodeBinary() { 202 if (Filesystem::binaryExists('nodejs')) { 203 return 'nodejs'; 204 } 205 206 if (Filesystem::binaryExists('node')) { 207 return 'node'; 208 } 209 210 throw new PhutilArgumentUsageException( 211 pht( 212 'No `nodejs` or `node` binary was found in $PATH. You must install '. 213 'Node.js to start the Aphlict server.')); 214 } 215 216 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |