@@ -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,43 @@ class Control extends Model {
279311 }
280312 }
281313
314+ public static async function genRunScript ($name ): Awaitable <void > {
315+ Utils :: logMessage(" Starting background script: $name " );
316+ $running = await self :: checkScriptRunning($name );
317+ if ($running ) {
318+ Utils :: logMessage(" Warning: $name is already running" );
319+ }
320+
321+ $document_root = Utils :: get_src_root();
322+ $cmd =
323+ " hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_$name " .
324+ $document_root .
325+ " /scripts/$name .php >> /var/log/fbctf/$name .log 2>&1 & echo $!" ;
326+ Utils :: logMessage(" Using command: [$cmd ]" );
327+ $pid = shell_exec ($cmd );
328+ await Control :: genStartScriptLog(intval ($pid ), $name , $cmd );
329+ }
330+
331+ public static async function genStopScript ($name ): Awaitable <void > {
332+ Utils :: logMessage(" Stopping background script: $name " );
333+
334+ do {
335+ // Kill running process
336+ $pid = await Control :: genScriptPid($name );
337+ if ($pid > 0 ) {
338+ Utils :: logMessage(" Killing $name with PID $pid " );
339+ exec (' kill -9 ' . escapeshellarg (strval ($pid )));
340+ }
341+ // Mark process as stopped
342+ await Control :: genStopScriptLog($pid );
343+ } while ($pid > 0 ); // In case there are multiple instances
344+ }
345+
282346 public static async function checkScriptRunning (
283347 string $name ,
284348 ): 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- }
349+ $pid = await self :: genScriptPid($name );
350+ return $pid !== 0 ;
306351 }
307352
308353 public static async function importGame (): Awaitable <bool > {
0 commit comments