From cb0cbc50ad0fc933e94f1bbe31f5f61aba05bf9e Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 13 Jun 2011 10:01:06 -0700 Subject: [PATCH] Add a "phd debug" command Summary: Make it easier to find obvious problems in daemons by letting them run undaemonized in the console without requiring the user to know the magical incantations for loading libraries, etc. Test Plan: Ran "phd debug nice", simulated some failures (e.g., bringing down Phabricator, daemon fatal) and got useful error messages. Reviewed By: jungejason Reviewers: toulouse, jungejason, tuomaspelkonen, aran CC: aran, jungejason Differential Revision: 448 --- .../daemon/phabricator_daemon_launcher.php | 35 ++++++++++++------- src/docs/managing_daemons.diviner | 5 +++ .../control/PhabricatorDaemonControl.php | 31 ++++++++++++---- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/scripts/daemon/phabricator_daemon_launcher.php b/scripts/daemon/phabricator_daemon_launcher.php index 671be82fef..2d1b528ef4 100755 --- a/scripts/daemon/phabricator_daemon_launcher.php +++ b/scripts/daemon/phabricator_daemon_launcher.php @@ -105,6 +105,9 @@ switch (isset($argv[1]) ? $argv[1] : 'help') { break; case 'launch': + case 'debug': + $is_debug = ($argv[1] == 'debug'); + $daemon = idx($argv, 2); if (!$daemon) { throw new Exception("Daemon name required!"); @@ -113,16 +116,18 @@ switch (isset($argv[1]) ? $argv[1] : 'help') { $pass_argv = array_slice($argv, 3); $n = 1; - if (is_numeric($daemon)) { - $n = $daemon; - if ($n < 1) { - throw new Exception("Count must be at least 1!"); + if (!$is_debug) { + if (is_numeric($daemon)) { + $n = $daemon; + if ($n < 1) { + throw new Exception("Count must be at least 1!"); + } + $daemon = idx($argv, 3); + if (!$daemon) { + throw new Exception("Daemon name required!"); + } + $pass_argv = array_slice($argv, 4); } - $daemon = idx($argv, 3); - if (!$daemon) { - throw new Exception("Daemon name required!"); - } - $pass_argv = array_slice($argv, 4); } $loader = new PhutilSymbolLoader(); @@ -154,11 +159,17 @@ switch (isset($argv[1]) ? $argv[1] : 'help') { $daemon = reset($match); } - echo "Launching {$n} x {$daemon}"; + if ($is_debug) { + echo "Launching {$daemon} in debug mode (nondaemonized)...\n"; + } else { + echo "Launching {$n} x {$daemon}"; + } for ($ii = 0; $ii < $n; $ii++) { - $control->launchDaemon($daemon, $pass_argv); - echo "."; + $control->launchDaemon($daemon, $pass_argv, $is_debug); + if (!$is_debug) { + echo "."; + } } echo "\n"; diff --git a/src/docs/managing_daemons.diviner b/src/docs/managing_daemons.diviner index 5fc2cec874..92c7d2ae78 100644 --- a/src/docs/managing_daemons.diviner +++ b/src/docs/managing_daemons.diviner @@ -34,6 +34,7 @@ a list of commands, run ##phd help##: Generally, you will use: - **phd launch** to launch daemons; + - **phd debug** to debug problems with daemons; - **phd status** to get a list of running daemons; and - **phd stop** to stop all daemons. @@ -54,6 +55,10 @@ allows you to view log information for them. If you have issues with daemons, you may be able to find error information that will help you resolve the problem in the console. +NOTE: The easiest way to figure out what's wrong with a daemon is usually to use +**phd debug** to launch it instead of **phd launch**. This will run it without +daemonizing it, so you can see output in your console. + = Available Daemons = You can get a list of launchable daemons with **phd list**: diff --git a/src/infrastructure/daemon/control/PhabricatorDaemonControl.php b/src/infrastructure/daemon/control/PhabricatorDaemonControl.php index cff0abf72b..4fab8ddb42 100644 --- a/src/infrastructure/daemon/control/PhabricatorDaemonControl.php +++ b/src/infrastructure/daemon/control/PhabricatorDaemonControl.php @@ -128,7 +128,10 @@ final class PhabricatorDaemonControl { **COMMAND REFERENCE** **launch** [__n__] __daemon__ [argv ...] + **debug** __daemon__ [argv ...] Start a daemon (or n copies of a daemon). + With **debug**, do not daemonize. Use this if you're having trouble + getting daemons working. **list** List available daemons. @@ -160,7 +163,7 @@ EOHELP return 1; } - public function launchDaemon($daemon, array $argv) { + public function launchDaemon($daemon, array $argv, $debug) { $symbols = $this->loadAvailableDaemonClasses(); $symbols = ipull($symbols, 'name', 'name'); if (empty($symbols[$daemon])) { @@ -195,24 +198,40 @@ EOHELP phutil_get_library_root($library)); } - $future = new ExecFuture( + $command = csprintf( "./launch_daemon.php ". "%s ". "--load-phutil-library=%s ". implode(' ', $extra_libraries)." ". "--conduit-uri=%s ". - "--daemonize ". "--phd=%s ". + ($debug ? '--trace ' : '--daemonize '). implode(' ', $argv), $daemon, phutil_get_library_root('phabricator'), PhabricatorEnv::getURI('/api/'), $pid_dir); - // Play games to keep 'ps' looking reasonable. - $future->setCWD($launch_daemon); + if ($debug) { + // Don't terminate when the user sends ^C; it will be sent to the + // subprocess which will terminate normally. + pcntl_signal( + SIGINT, + array('PhabricatorDaemonControl', 'ignoreSignal')); - $future->resolvex(); + echo "\n libphutil/scripts/daemon/ \$ {$command}\n\n"; + + phutil_passthru('(cd %s && exec %C)', $launch_daemon, $command); + } else { + $future = new ExecFuture('exec %C', $command); + // Play games to keep 'ps' looking reasonable. + $future->setCWD($launch_daemon); + $future->resolvex(); + } + } + + public static function ignoreSignal($signo) { + return; } protected function getControlDirectory($dir) {