Skip to content

Commit cb0cbc5

Browse files
author
epriestley
committed
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
1 parent 33e6229 commit cb0cbc5

File tree

3 files changed

+53
-18
lines changed

3 files changed

+53
-18
lines changed

scripts/daemon/phabricator_daemon_launcher.php

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@
105105
break;
106106

107107
case 'launch':
108+
case 'debug':
109+
$is_debug = ($argv[1] == 'debug');
110+
108111
$daemon = idx($argv, 2);
109112
if (!$daemon) {
110113
throw new Exception("Daemon name required!");
@@ -113,16 +116,18 @@
113116
$pass_argv = array_slice($argv, 3);
114117

115118
$n = 1;
116-
if (is_numeric($daemon)) {
117-
$n = $daemon;
118-
if ($n < 1) {
119-
throw new Exception("Count must be at least 1!");
120-
}
121-
$daemon = idx($argv, 3);
122-
if (!$daemon) {
123-
throw new Exception("Daemon name required!");
119+
if (!$is_debug) {
120+
if (is_numeric($daemon)) {
121+
$n = $daemon;
122+
if ($n < 1) {
123+
throw new Exception("Count must be at least 1!");
124+
}
125+
$daemon = idx($argv, 3);
126+
if (!$daemon) {
127+
throw new Exception("Daemon name required!");
128+
}
129+
$pass_argv = array_slice($argv, 4);
124130
}
125-
$pass_argv = array_slice($argv, 4);
126131
}
127132

128133
$loader = new PhutilSymbolLoader();
@@ -154,11 +159,17 @@
154159
$daemon = reset($match);
155160
}
156161

157-
echo "Launching {$n} x {$daemon}";
162+
if ($is_debug) {
163+
echo "Launching {$daemon} in debug mode (nondaemonized)...\n";
164+
} else {
165+
echo "Launching {$n} x {$daemon}";
166+
}
158167

159168
for ($ii = 0; $ii < $n; $ii++) {
160-
$control->launchDaemon($daemon, $pass_argv);
161-
echo ".";
169+
$control->launchDaemon($daemon, $pass_argv, $is_debug);
170+
if (!$is_debug) {
171+
echo ".";
172+
}
162173
}
163174

164175
echo "\n";

src/docs/managing_daemons.diviner

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ a list of commands, run ##phd help##:
3434
Generally, you will use:
3535

3636
- **phd launch** to launch daemons;
37+
- **phd debug** to debug problems with daemons;
3738
- **phd status** to get a list of running daemons; and
3839
- **phd stop** to stop all daemons.
3940

@@ -54,6 +55,10 @@ allows you to view log information for them. If you have issues with daemons,
5455
you may be able to find error information that will help you resolve the problem
5556
in the console.
5657

58+
NOTE: The easiest way to figure out what's wrong with a daemon is usually to use
59+
**phd debug** to launch it instead of **phd launch**. This will run it without
60+
daemonizing it, so you can see output in your console.
61+
5762
= Available Daemons =
5863

5964
You can get a list of launchable daemons with **phd list**:

src/infrastructure/daemon/control/PhabricatorDaemonControl.php

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,10 @@ public function executeHelpCommand() {
128128
**COMMAND REFERENCE**
129129
130130
**launch** [__n__] __daemon__ [argv ...]
131+
**debug** __daemon__ [argv ...]
131132
Start a daemon (or n copies of a daemon).
133+
With **debug**, do not daemonize. Use this if you're having trouble
134+
getting daemons working.
132135
133136
**list**
134137
List available daemons.
@@ -160,7 +163,7 @@ public function executeHelpCommand() {
160163
return 1;
161164
}
162165

163-
public function launchDaemon($daemon, array $argv) {
166+
public function launchDaemon($daemon, array $argv, $debug) {
164167
$symbols = $this->loadAvailableDaemonClasses();
165168
$symbols = ipull($symbols, 'name', 'name');
166169
if (empty($symbols[$daemon])) {
@@ -195,24 +198,40 @@ public function launchDaemon($daemon, array $argv) {
195198
phutil_get_library_root($library));
196199
}
197200

198-
$future = new ExecFuture(
201+
$command = csprintf(
199202
"./launch_daemon.php ".
200203
"%s ".
201204
"--load-phutil-library=%s ".
202205
implode(' ', $extra_libraries)." ".
203206
"--conduit-uri=%s ".
204-
"--daemonize ".
205207
"--phd=%s ".
208+
($debug ? '--trace ' : '--daemonize ').
206209
implode(' ', $argv),
207210
$daemon,
208211
phutil_get_library_root('phabricator'),
209212
PhabricatorEnv::getURI('/api/'),
210213
$pid_dir);
211214

212-
// Play games to keep 'ps' looking reasonable.
213-
$future->setCWD($launch_daemon);
215+
if ($debug) {
216+
// Don't terminate when the user sends ^C; it will be sent to the
217+
// subprocess which will terminate normally.
218+
pcntl_signal(
219+
SIGINT,
220+
array('PhabricatorDaemonControl', 'ignoreSignal'));
221+
222+
echo "\n libphutil/scripts/daemon/ \$ {$command}\n\n";
223+
224+
phutil_passthru('(cd %s && exec %C)', $launch_daemon, $command);
225+
} else {
226+
$future = new ExecFuture('exec %C', $command);
227+
// Play games to keep 'ps' looking reasonable.
228+
$future->setCWD($launch_daemon);
229+
$future->resolvex();
230+
}
231+
}
214232

215-
$future->resolvex();
233+
public static function ignoreSignal($signo) {
234+
return;
216235
}
217236

218237
protected function getControlDirectory($dir) {

0 commit comments

Comments
 (0)