From c80084b025e5556f1b7b51101ca1f7b9a0b47db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 18 Oct 2015 13:04:04 +0200 Subject: [PATCH] JobQueue: fixed incorrect requeuing. * A dependent job was requeued even if it wasn't part of the queue before. The code relied on dependent jobs being already enqueued; but that cannot be guaranteed. * If a job failed, its dependent jobs are now also set to failed, so that they won't be requeued at a later point. * This caused some of the "Launching xxx failed: Operation not allowed" messages in the boot process. Those actually weren't harmless, and could mess up the natural job order. --- headers/private/support/JobPrivate.h | 10 +++++++++ src/kits/support/JobQueue.cpp | 31 +++++++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/headers/private/support/JobPrivate.h b/headers/private/support/JobPrivate.h index 8e9ae814d0..7ed4a25162 100644 --- a/headers/private/support/JobPrivate.h +++ b/headers/private/support/JobPrivate.h @@ -30,6 +30,16 @@ public: fJob._ClearTicketNumber(); } + void SetState(BJobState state) + { + fJob.SetState(state); + } + + void NotifyStateListeners() + { + fJob.NotifyStateListeners(); + } + private: BJob& fJob; }; diff --git a/src/kits/support/JobQueue.cpp b/src/kits/support/JobQueue.cpp index 974903941d..13e48ce124 100644 --- a/src/kits/support/JobQueue.cpp +++ b/src/kits/support/JobQueue.cpp @@ -243,16 +243,24 @@ void JobQueue::_RequeueDependantJobsOf(BJob* job) { while (BJob* dependantJob = job->DependantJobAt(0)) { - try { - fQueuedJobs->erase(dependantJob); - } catch (...) { + JobPriorityQueue::iterator found = fQueuedJobs->find(dependantJob); + bool removed = false; + if (found != fQueuedJobs->end()) { + try { + fQueuedJobs->erase(dependantJob); + removed = true; + } catch (...) { + } } dependantJob->RemoveDependency(job); - try { - fQueuedJobs->insert(dependantJob); - if (dependantJob->IsRunnable()) - release_sem(fHaveRunnableJobSem); - } catch (...) { + if (removed) { + // Only insert a job if it was in our queue before + try { + fQueuedJobs->insert(dependantJob); + if (dependantJob->IsRunnable()) + release_sem(fHaveRunnableJobSem); + } catch (...) { + } } } } @@ -266,8 +274,15 @@ JobQueue::_RemoveDependantJobsOf(BJob* job) fQueuedJobs->erase(dependantJob); } catch (...) { } + + if (dependantJob->State() != B_JOB_STATE_ABORTED) { + BJob::Private(*dependantJob).SetState(B_JOB_STATE_ABORTED); + BJob::Private(*dependantJob).NotifyStateListeners(); + } + _RemoveDependantJobsOf(dependantJob); dependantJob->RemoveDependency(job); + // TODO: we need some sort of ownership management delete dependantJob; } }