Skip to content

Commit bcb059f

Browse files
committed
Add SIGALRM to kill stuck workers
1 parent 1381dd3 commit bcb059f

2 files changed

Lines changed: 28 additions & 4 deletions

File tree

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"illuminate/encryption": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0",
2929
"guzzlehttp/guzzle": "^6.5.5|^7.2",
3030
"jfcherng/php-diff": "^6.13",
31-
"doctrine/dbal": "^3.3|^4.0"
31+
"doctrine/dbal": "^3.3|^4.0",
32+
"ext-posix": "*"
3233
},
3334
"require-dev": {
3435
"cego/php-cs-fixer": "^2.0",

src/RequestInsurance/RequestInsuranceWorker.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public function run(bool $runOnlyOnce = false): void
6969

7070
do {
7171
try {
72+
$this->registerTimeoutHandler();
73+
7274
if (Config::get('request-insurance.useDbReconnect')) {
7375
DB::reconnect();
7476
}
@@ -84,16 +86,18 @@ public function run(bool $runOnlyOnce = false): void
8486

8587
usleep($waitTime);
8688
} catch (Throwable $throwable) {
89+
$this->resetTimeoutHandler(); // We need to reset here before logging the error and sleeping, otherwise the timeout handler might trigger while we are sleeping/logging, which is not desirable.
90+
8791
Log::error($throwable);
8892

8993
if ($runOnlyOnce) {
9094
throw $throwable;
9195
}
9296

93-
sleep(5); // Sleep to avoid spamming the log
97+
usleep(100_000); // Sleep to avoid spamming the log
98+
} finally {
99+
$this->resetTimeoutHandler();
94100
}
95-
96-
pcntl_signal_dispatch();
97101
} while ( ! $runOnlyOnce && ! $this->shutdownSignalReceived);
98102

99103
Log::info(sprintf('RequestInsurance Worker (#%s) has gracefully stopped', $this->runningHash));
@@ -107,6 +111,7 @@ public function run(bool $runOnlyOnce = false): void
107111
*/
108112
protected function setupShutdownSignalHandler(): void
109113
{
114+
pcntl_async_signals(true);
110115
pcntl_signal(SIGQUIT, [$this, 'sig_handler']); // Code 3
111116
pcntl_signal(SIGTERM, [$this, 'sig_handler']); // Code 15
112117
}
@@ -327,4 +332,22 @@ public function getIdsOfReadyRequests()
327332

328333
return $builder->pluck('id');
329334
}
335+
336+
private function registerTimeoutHandler()
337+
{
338+
pcntl_signal(SIGALRM, function () {
339+
Log::debug('Timeout handler was triggered indicating stuck worker, exiting...');
340+
341+
if (($pid = getmypid()) === false) {
342+
posix_kill($pid, SIGKILL);
343+
}
344+
exit(1);
345+
});
346+
pcntl_alarm(Config::integer('request-insurance.maximumSecondsPerWorkerCycle', 60));
347+
}
348+
349+
private function resetTimeoutHandler(): void
350+
{
351+
pcntl_alarm(0);
352+
}
330353
}

0 commit comments

Comments
 (0)