aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2025-07-24 00:47:37 +0200
committerJoas Schilling <coding@schilljs.com>2025-07-25 15:28:24 +0200
commit031d739d3327e324d782f9890ec82fe6774226bd (patch)
treec7ff5f911810c479b4c1f7b99f03eb80d9a0389a
parentde46e39405c4ea10eaa2cb7f46edeb6f29c8edbf (diff)
downloadnextcloud-server-bugfix/noid/fix-infinite-loop-on-parallelaware-block.tar.gz
nextcloud-server-bugfix/noid/fix-infinite-loop-on-parallelaware-block.zip
fix(cron): Fix infinite loop on ParallelAware blocked jobsbugfix/noid/fix-infinite-loop-on-parallelaware-block
Signed-off-by: Joas Schilling <coding@schilljs.com>
-rw-r--r--lib/private/BackgroundJob/JobList.php13
1 files changed, 13 insertions, 0 deletions
diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php
index 0d88200cff7..c00a51e3851 100644
--- a/lib/private/BackgroundJob/JobList.php
+++ b/lib/private/BackgroundJob/JobList.php
@@ -24,6 +24,9 @@ use function min;
use function strlen;
class JobList implements IJobList {
+ /** @var array<string, int> */
+ protected array $alreadyVisitedParallelBlocked = [];
+
public function __construct(
protected IDBConnection $connection,
protected IConfig $config,
@@ -198,6 +201,12 @@ class JobList implements IJobList {
$job = $this->buildJob($row);
if ($job instanceof IParallelAwareJob && !$job->getAllowParallelRuns() && $this->hasReservedJob(get_class($job))) {
+ if (!isset($this->alreadyVisitedParallelBlocked[get_class($job)])) {
+ $this->alreadyVisitedParallelBlocked[get_class($job)] = $job->getId();
+ } elseif ($this->alreadyVisitedParallelBlocked[get_class($job)] === $job->getId()) {
+ $this->logger->info('Skipped through all jobs and revisited a IParallelAwareJob blocked job again, giving up.', ['app' => 'cron']);
+ return null;
+ }
$this->logger->info('Skipping ' . get_class($job) . ' job with ID ' . $job->getId() . ' because another job with the same class is already running', ['app' => 'cron']);
$update = $this->connection->getQueryBuilder();
@@ -210,6 +219,10 @@ class JobList implements IJobList {
return $this->getNext($onlyTimeSensitive, $jobClasses);
}
+ if ($job !== null && isset($this->alreadyVisitedParallelBlocked[get_class($job)])) {
+ unset($this->alreadyVisitedParallelBlocked[get_class($job)]);
+ }
+
if ($job instanceof \OCP\BackgroundJob\TimedJob) {
$now = $this->timeFactory->getTime();
$nextPossibleRun = $job->getLastRun() + $job->getInterval();