@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at recaptime-dev/main 131 lines 3.1 kB view raw
1#!/usr/bin/env php 2<?php 3 4if (function_exists('pcntl_async_signals')) { 5 pcntl_async_signals(true); 6} else { 7 declare(ticks = 1); 8} 9 10require_once dirname(__FILE__).'/../../__init_script__.php'; 11 12if (!posix_isatty(STDOUT)) { 13 $sid = posix_setsid(); 14 if ($sid <= 0) { 15 throw new Exception(pht('Failed to create new process session!')); 16 } 17} 18 19$args = new PhutilArgumentParser($argv); 20$args->setTagline(pht('daemon executor')); 21$args->setSynopsis(pht(<<<EOHELP 22**exec_daemon.php** [__options__] __daemon__ ... 23 Run an instance of __daemon__. 24EOHELP 25 )); 26$args->parse( 27 array( 28 array( 29 'name' => 'trace', 30 'help' => pht('Enable debug tracing.'), 31 ), 32 array( 33 'name' => 'trace-memory', 34 'help' => pht('Enable debug memory tracing.'), 35 ), 36 array( 37 'name' => 'verbose', 38 'help' => pht('Enable verbose activity logging.'), 39 ), 40 array( 41 'name' => 'label', 42 'short' => 'l', 43 'param' => 'label', 44 'help' => pht( 45 'Optional process label. Makes "%s" nicer, no behavioral effects.', 46 'ps'), 47 ), 48 array( 49 'name' => 'daemon', 50 'wildcard' => true, 51 ), 52 )); 53 54$trace_memory = $args->getArg('trace-memory'); 55$trace_mode = $args->getArg('trace') || $trace_memory; 56$verbose = $args->getArg('verbose'); 57 58if (function_exists('posix_isatty') && posix_isatty(STDIN)) { 59 fprintf(STDERR, pht('Reading daemon configuration from stdin...')."\n"); 60} 61$config = @file_get_contents('php://stdin'); 62$config = id(new PhutilJSONParser())->parse($config); 63 64PhutilTypeSpec::checkMap( 65 $config, 66 array( 67 'log' => 'optional string|null', 68 'argv' => 'optional list<wild>', 69 'load' => 'optional list<string>', 70 'down' => 'optional int', 71 )); 72 73$log = idx($config, 'log'); 74 75if ($log) { 76 ini_set('error_log', $log); 77 PhutilErrorHandler::setErrorListener(array('PhutilDaemon', 'errorListener')); 78} 79 80$load = idx($config, 'load', array()); 81foreach ($load as $library) { 82 $library = Filesystem::resolvePath($library); 83 phutil_load_library($library); 84} 85 86PhutilErrorHandler::initialize(); 87 88$daemon = $args->getArg('daemon'); 89if (!$daemon) { 90 throw new PhutilArgumentUsageException( 91 pht('Specify which class of daemon to start.')); 92} else if (count($daemon) > 1) { 93 throw new PhutilArgumentUsageException( 94 pht('Specify exactly one daemon to start.')); 95} else { 96 $daemon = head($daemon); 97 if (!class_exists($daemon)) { 98 throw new PhutilArgumentUsageException( 99 pht( 100 'No class "%s" exists in any known library.', 101 $daemon)); 102 } else if (!is_subclass_of($daemon, PhutilDaemon::class)) { 103 throw new PhutilArgumentUsageException( 104 pht( 105 'Class "%s" is not a subclass of "%s".', 106 $daemon, 107 'PhutilDaemon')); 108 } 109} 110 111$argv = idx($config, 'argv', array()); 112$daemon = newv($daemon, array($argv)); 113 114if ($trace_mode) { 115 $daemon->setTraceMode(); 116} 117 118if ($trace_memory) { 119 $daemon->setTraceMemory(); 120} 121 122if ($verbose) { 123 $daemon->setVerbose(true); 124} 125 126$down_duration = idx($config, 'down'); 127if ($down_duration) { 128 $daemon->setScaledownDuration($down_duration); 129} 130 131$daemon->execute();