@@ -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 > {
0 commit comments