@@ -51,6 +51,12 @@ class AsyncTask
5151 */
5252 private int $ timerProcID = 0 ;
5353
54+ /**
55+ * On Unix only. Indicates whether a SIGINT has been received.
56+ * @var bool
57+ */
58+ private bool $ hasSigInt = false ;
59+
5460 /**
5561 * The string constant name for constant('LARAVEL_START'). Mainly to keep the code clean.
5662 * @var string
@@ -118,9 +124,10 @@ public function run(): void
118124 // assume anything not Windows to be Unix
119125 // 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
120126 pcntl_async_signals (true );
121- pcntl_signal (SIGTERM , function () {
122- // just exit is ok
127+ pcntl_signal (SIGINT , function () {
128+ // sicne we are already running with nohup, we can use SIGINT to indicate that a timeout has occurred.
123129 // exit asap so that our error checking inside shutdown functions can take place outside of the usual max_execution_time limit
130+ $ this ->hasSigInt = true ;
124131 exit ();
125132 });
126133
@@ -184,7 +191,8 @@ public function start(): void
184191 // can't do anything without GNU coreutils!
185192 throw new RuntimeException ("AsyncTask time limit requires GNU coreutils, but GNU coreutils was not installed " );
186193 }
187- $ timeoutClause = static ::$ timeoutCmdName . " {$ this ->timeLimit }" ;
194+ // 2 is INT signal
195+ $ timeoutClause = static ::$ timeoutCmdName . " -s 2 {$ this ->timeLimit }" ;
188196 }
189197 $ this ->runnerProcess = Process::quietly ()->start ("nohup $ timeoutClause $ baseCommand >/dev/null 2>&1 " );
190198 }
@@ -299,6 +307,11 @@ private function hasTimedOut(): bool
299307 {
300308 // we perform a series of checks to see if this task has timed out
301309
310+ // dedicated SIGINT indicates a timeout
311+ if ($ this ->hasSigInt ) {
312+ return true ;
313+ }
314+
302315 // runtime timeout triggers a PHP fatal error
303316 // this can happen on Windows by our specification, or on Unix when the actual CLI PHP time limit is smaller than the time limit of this task
304317 $ lastError = error_get_last ();
@@ -334,8 +347,7 @@ private function hasTimedOut(): bool
334347 $ timeElapsed = (int ) $ tempOut ;
335348 unset($ tempOut );
336349 // 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 ;
350+ return $ timeElapsed >= $ this ->timeLimit ;
339351 }
340352 }
341353
0 commit comments