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.
This commit is contained in:
Axel Dörfler
2015-10-18 13:11:26 +02:00
parent e21da03a34
commit c80084b025
2 changed files with 33 additions and 8 deletions
+10
View File
@@ -30,6 +30,16 @@ public:
fJob._ClearTicketNumber(); fJob._ClearTicketNumber();
} }
void SetState(BJobState state)
{
fJob.SetState(state);
}
void NotifyStateListeners()
{
fJob.NotifyStateListeners();
}
private: private:
BJob& fJob; BJob& fJob;
}; };
+23 -8
View File
@@ -243,16 +243,24 @@ void
JobQueue::_RequeueDependantJobsOf(BJob* job) JobQueue::_RequeueDependantJobsOf(BJob* job)
{ {
while (BJob* dependantJob = job->DependantJobAt(0)) { while (BJob* dependantJob = job->DependantJobAt(0)) {
try { JobPriorityQueue::iterator found = fQueuedJobs->find(dependantJob);
fQueuedJobs->erase(dependantJob); bool removed = false;
} catch (...) { if (found != fQueuedJobs->end()) {
try {
fQueuedJobs->erase(dependantJob);
removed = true;
} catch (...) {
}
} }
dependantJob->RemoveDependency(job); dependantJob->RemoveDependency(job);
try { if (removed) {
fQueuedJobs->insert(dependantJob); // Only insert a job if it was in our queue before
if (dependantJob->IsRunnable()) try {
release_sem(fHaveRunnableJobSem); fQueuedJobs->insert(dependantJob);
} catch (...) { if (dependantJob->IsRunnable())
release_sem(fHaveRunnableJobSem);
} catch (...) {
}
} }
} }
} }
@@ -266,8 +274,15 @@ JobQueue::_RemoveDependantJobsOf(BJob* job)
fQueuedJobs->erase(dependantJob); fQueuedJobs->erase(dependantJob);
} catch (...) { } catch (...) {
} }
if (dependantJob->State() != B_JOB_STATE_ABORTED) {
BJob::Private(*dependantJob).SetState(B_JOB_STATE_ABORTED);
BJob::Private(*dependantJob).NotifyStateListeners();
}
_RemoveDependantJobsOf(dependantJob); _RemoveDependantJobsOf(dependantJob);
dependantJob->RemoveDependency(job); dependantJob->RemoveDependency(job);
// TODO: we need some sort of ownership management
delete dependantJob; delete dependantJob;
} }
} }