Skip to content

Commit 5c129d5

Browse files
committed
Cleanup the task runner
1 parent 6fe7c6c commit 5c129d5

File tree

1 file changed

+10
-34
lines changed

1 file changed

+10
-34
lines changed

src/AsyncTask.php

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,6 @@ class AsyncTask
5757
*/
5858
private const LARAVEL_START = "LARAVEL_START";
5959

60-
/**
61-
* The epsilon time (in seconds) that will be added to the microtime to check for task timeouts.
62-
*
63-
* For some unknown reason, theoretical solutions that rely on (supposed) Unix behavior does not pass the tests,
64-
* so we are implementing this as a temporary workaround.
65-
* @var float
66-
*/
67-
private const TIME_EPSILON = 0.1;
68-
6960
/**
7061
* The bitmask that can filter for fatal runtime errors.
7162
*
@@ -125,9 +116,13 @@ public function run(): void
125116
set_time_limit($this->timeLimit);
126117
} else {
127118
// assume anything not Windows to be Unix
128-
// we already set it to kill this task after the timeout, so we just need to install a listener
119+
// we already set it to kill this task after the timeout, so we just need to install a listener to catch the signal and exit gracefully
129120
pcntl_async_signals(true);
130-
pcntl_signal(SIGTERM, [$this, 'pcntlGracefulExit']);
121+
pcntl_signal(SIGTERM, function () {
122+
// just exit is ok
123+
// exit asap so that our error checking inside shutdown functions can take place outside of the usual max_execution_time limit
124+
exit();
125+
});
131126

132127
// and we also need to see the command name of our parent, to correctly track time
133128
$this->timerProcID = getmypid();
@@ -191,8 +186,7 @@ public function start(): void
191186
}
192187
$timeoutClause = static::$timeoutCmdName . " {$this->timeLimit}";
193188
}
194-
// $this->runnerProcess = Process::quietly()->start("nohup $timeoutClause $baseCommand >/dev/null 2>&1");
195-
$this->runnerProcess = Process::quietly()->start("nohup $timeoutClause $baseCommand");
189+
$this->runnerProcess = Process::quietly()->start("nohup $timeoutClause $baseCommand >/dev/null 2>&1");
196190
}
197191

198192
/**
@@ -277,19 +271,6 @@ public function withoutTimeLimit(): static
277271
return $this;
278272
}
279273

280-
/**
281-
* On Unix only. Signal handler for SIGTERM to catch it and exit() instead.
282-
*
283-
* NOT FOR EXTERNAL USE!
284-
* @return never
285-
*/
286-
public function pcntlGracefulExit(): never
287-
{
288-
// just exit is ok
289-
// exit asap so that our error checking inside shutdown functions can take place outside of the usual max_execution_time limit
290-
exit();
291-
}
292-
293274
/**
294275
* A shutdown function.
295276
*
@@ -323,7 +304,6 @@ private function hasTimedOut(): bool
323304
$lastError = error_get_last();
324305
if ($lastError !== null && ($lastError['type'] & self::FATAL_ERROR_BITMASK)) {
325306
// has fatal error; is it our timeout error?
326-
fwrite(STDERR, "error_get_last " . json_encode($lastError) . PHP_EOL);
327307
return str_contains($lastError['message'], "Maximum execution time");
328308
}
329309
unset($lastError);
@@ -338,8 +318,6 @@ private function hasTimedOut(): bool
338318

339319
// check LARAVEL_START with microtime
340320
$timeElapsed = microtime(true) - $this->laravelStartVal;
341-
// temp let runner print me the stats
342-
fwrite(STDERR, "microtime elapsed $timeElapsed" . PHP_EOL);
343321
if ($timeElapsed >= $this->timeLimit) {
344322
// yes
345323
return true;
@@ -354,12 +332,10 @@ private function hasTimedOut(): bool
354332
$tempOut = exec("ps -p {$this->timerProcID} -o etimes=");
355333
// this must exist (we are still running!), otherwise it indicates the kernel is broken and we can go grab a chicken dinner instead
356334
$timeElapsed = (int) $tempOut;
357-
fwrite(STDERR, "proc-stat elapsed $timeElapsed" . PHP_EOL);
358335
unset($tempOut);
359-
// we believe there is a seemingly unexplainable behavior that results in the etimes to be off-by-1 when it would be terminated by `timeout`
360-
// e.g., when killed by `timeout` with time limit = 7, the etime might actually be 6.999999... and it gets displayed as 6, thus failing the check
361-
// so, just to be sure, we will make it timeout when killed at the last second to the time limit
362-
return $timeElapsed >= $this->timeLimit;
336+
// it seems like etimes can get random off-by-1 inaccuracies (e.g. timeout supposed to be 7, but etimes sees 6.99999... and prints "6")
337+
// so, we will still trigger the timeout handler if the runner is killed in its last second of execution; we trust the timeout command for this
338+
return $timeElapsed + 1 >= $this->timeLimit;
363339
}
364340
}
365341

0 commit comments

Comments
 (0)