Skip to content
This repository was archived by the owner on Mar 3, 2020. It is now read-only.

Commit 2faea51

Browse files
committed
Make background scripts more reliable
- Move starting & stopping to `Control`, and call those methods - Keeping autorun separate to avoid spamming the log files - Check whether a script is running before attempting to start it - Check actual process IDs, rather than hoping the database is accurate - Kill all instances of a script, rather than just the one in the DB - More logging to make debugging easier
1 parent 30688d9 commit 2faea51

File tree

3 files changed

+75
-54
lines changed

3 files changed

+75
-54
lines changed

src/models/Control.php

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,37 @@ class Control extends Model {
5252
if ($result->numRows() > 0) {
5353
$pid = intval(must_have_idx($result->mapRows()[0], 'pid'));
5454
}
55-
return $pid;
55+
56+
// Check that the process is actually running
57+
$actual_pid = await self::genRunningScriptPid($name);
58+
if ($pid == $actual_pid) {
59+
return $pid;
60+
}
61+
if ($actual_pid == 0 && $pid != 0) {
62+
Utils::logMessage("Warning: Script ($name) started as PID $pid but is no longer running");
63+
await self::genStopScriptLog($pid);
64+
} else if ($actual_pid != 0 && $pid == 0) {
65+
Utils::logMessage("Warning: Script ($name) was not started, but is running as PID $actual_pid");
66+
} else if ($actual_pid != $pid) {
67+
Utils::logMessage("Warning: Script ($name) started as PID $pid but is actually running as $actual_pid");
68+
await self::genStopScriptLog($pid);
69+
}
70+
71+
return $actual_pid;
72+
}
73+
74+
public static async function genRunningScriptPid(string $name): Awaitable<int> {
75+
$lines = array();
76+
exec( "ps -C hhvm --format 'pid args' | grep '$name.php'", $lines );
77+
if (count($lines) === 0) {
78+
return 0;
79+
} else if (count($lines) > 1) {
80+
Utils::logMessage("Error: multiple instances of ($name.php) running!");
81+
}
82+
83+
$matches = array();
84+
$results = preg_match('/\s*([0-9]+)\s/', $lines[0], $matches);
85+
return $results > 0 ? intval($matches[1]) : 0;
5686
}
5787

5888
public static async function genClearScriptLog(): Awaitable<void> {
@@ -166,6 +196,7 @@ class Control extends Model {
166196
}
167197

168198
public static async function genPause(): Awaitable<void> {
199+
Utils::logMessage('Pausing game');
169200
await \HH\Asio\va(
170201
Announcement::genCreateAuto('Game has been paused!'), // Announce game paused
171202
ActivityLog::genCreateGenericLog('Game has been paused!'), // Log game paused
@@ -183,6 +214,7 @@ class Control extends Model {
183214
}
184215

185216
public static async function genUnpause(): Awaitable<void> {
217+
Utils::logMessage('Unpausing game');
186218
await Configuration::genUpdate('scoring', '1'); // Enable scoring
187219
list($config_pause_ts, $config_start_ts, $config_end_ts) =
188220
await \HH\Asio\va(
@@ -279,30 +311,47 @@ class Control extends Model {
279311
}
280312
}
281313

314+
public static async function genRunScript(
315+
string $name
316+
): Awaitable<void> {
317+
Utils::logMessage("Starting background script: $name");
318+
$running = await self::checkScriptRunning($name);
319+
if ($running) {
320+
Utils::logMessage("Warning: $name is already running");
321+
}
322+
323+
$document_root = Utils::get_src_root();
324+
$cmd =
325+
"hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_$name ".
326+
$document_root.
327+
"/scripts/$name.php >> /var/log/fbctf/$name.log 2>&1 & echo $!";
328+
Utils::logMessage("Using command: [$cmd]");
329+
$pid = shell_exec($cmd);
330+
await Control::genStartScriptLog(intval($pid), $name, $cmd);
331+
}
332+
333+
public static async function genStopScript(
334+
string $name
335+
): Awaitable<void> {
336+
Utils::logMessage("Stopping background script: $name");
337+
338+
do {
339+
// Kill running process
340+
$pid = await Control::genScriptPid($name);
341+
if ($pid > 0) {
342+
Utils::logMessage("Killing $name with PID $pid");
343+
exec('kill -9 '.escapeshellarg(strval($pid)));
344+
}
345+
// Mark process as stopped
346+
await Control::genStopScriptLog($pid);
347+
} while ($pid > 0); // In case there are multiple instances
348+
}
349+
282350
public static async function checkScriptRunning(
283351
string $name,
284352
): Awaitable<bool> {
285-
$db = await self::genDb();
286-
$host = await Control::genServerAddr();
287-
$result = await $db->queryf(
288-
'SELECT pid FROM scripts WHERE name = %s AND host = %s AND status = 1',
289-
$name,
290-
$host,
291-
);
292-
$status = false;
293-
if ($result->numRows() >= 1) {
294-
foreach ($result->mapRows() as $row) {
295-
$pid = intval(must_have_idx($row, 'pid'));
296-
$status = file_exists("/proc/$pid");
297-
if ($status === false) {
298-
await Control::genStopScriptLog($pid);
299-
await Control::genClearScriptLog();
300-
}
301-
}
302-
return $status;
303-
} else {
304-
return false;
305-
}
353+
$pid = await self::genScriptPid($name);
354+
return $pid !== 0;
306355
}
307356

308357
public static async function importGame(): Awaitable<bool> {

src/models/Level.php

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,26 +1283,12 @@ public static function getBasesResponses(
12831283

12841284
// Bases processing and scoring.
12851285
public static async function genBaseScoring(): Awaitable<void> {
1286-
Utils::logMessage('Starting background script: bases');
1287-
$document_root = Utils::get_src_root();
1288-
$cmd =
1289-
'hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_bases '.
1290-
$document_root.
1291-
'/scripts/bases.php >> /var/log/fbctf/bases.log 2>&1 & echo $!';
1292-
Utils::logMessage("Using command: [$cmd]");
1293-
$pid = shell_exec($cmd);
1294-
await Control::genStartScriptLog(intval($pid), 'bases', $cmd);
1286+
await Control::genRunScript('bases');
12951287
}
12961288

12971289
// Stop bases processing and scoring process.
12981290
public static async function genStopBaseScoring(): Awaitable<void> {
1299-
// Kill running process
1300-
$pid = await Control::genScriptPid('bases');
1301-
if ($pid > 0) {
1302-
exec('kill -9 '.escapeshellarg(strval($pid)));
1303-
}
1304-
// Mark process as stopped
1305-
await Control::genStopScriptLog($pid);
1291+
await Control::genStopScript('bases');
13061292
}
13071293

13081294
// Check if a level already exists by type, title and entity.

src/models/Progressive.php

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -146,25 +146,11 @@ private static function progressiveFromRow(
146146

147147
// Kick off the progressive scoreboard in the background.
148148
public static async function genRun(): Awaitable<void> {
149-
Utils::logMessage('Starting background script: progressive scoreboard');
150-
$document_root = Utils::get_src_root();
151-
$cmd =
152-
'hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_progressive '.
153-
$document_root.
154-
"/scripts/progressive.php >> /var/log/fbctf/progressive.log 2>&1 & echo $!";
155-
Utils::logMessage("Using command: [$cmd]");
156-
$pid = shell_exec($cmd);
157-
await Control::genStartScriptLog(intval($pid), 'progressive', $cmd);
149+
await Control::genRunScript('progressive');
158150
}
159151

160152
// Stop the progressive scoreboard process in the background
161153
public static async function genStop(): Awaitable<void> {
162-
// Kill running process
163-
$pid = await Control::genScriptPid('progressive');
164-
if ($pid > 0) {
165-
exec('kill -9 '.escapeshellarg(strval($pid)));
166-
}
167-
// Mark process as stopped
168-
await Control::genStopScriptLog($pid);
154+
await Control::genStopScript('progressive');
169155
}
170156
}

0 commit comments

Comments
 (0)