|
Michal Schmidt |
bbee01 |
From 563ba9ea6e60774086555998b957edf923e24b46 Mon Sep 17 00:00:00 2001
|
|
Michal Schmidt |
bbee01 |
From: Michal Schmidt <mschmidt@redhat.com>
|
|
Michal Schmidt |
bbee01 |
Date: Mon, 17 Oct 2011 11:12:12 +0200
|
|
Michal Schmidt |
bbee01 |
Subject: [PATCH 2/5] manager: fix a crash in isolating
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
HASHMAP_FOREACH is safe against the removal of the current entry, but
|
|
Michal Schmidt |
bbee01 |
not against the removal of other entries. job_finish_and_invalidate()
|
|
Michal Schmidt |
bbee01 |
can recursively remove other entries.
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
It triggered an assertion failure:
|
|
Michal Schmidt |
bbee01 |
Assertion 'j->installed' failed at src/manager.c:1218, function
|
|
Michal Schmidt |
bbee01 |
transaction_apply(). Aborting.
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
Fix the crash by iterating from the beginning when there is a
|
|
Michal Schmidt |
bbee01 |
possibility that the iterator could be invalid.
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
It is O(n^2) in the worst case, but that's better than a crash.
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
https://bugzilla.redhat.com/show_bug.cgi?id=717325
|
|
Michal Schmidt |
bbee01 |
---
|
|
Michal Schmidt |
bbee01 |
src/job.c | 19 ++++++++++++++-----
|
|
Michal Schmidt |
bbee01 |
src/manager.c | 7 ++++++-
|
|
Michal Schmidt |
bbee01 |
2 files changed, 20 insertions(+), 6 deletions(-)
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
diff --git a/src/job.c b/src/job.c
|
|
Michal Schmidt |
bbee01 |
index 5c0913b..20971da 100644
|
|
Michal Schmidt |
bbee01 |
--- a/src/job.c
|
|
Michal Schmidt |
bbee01 |
+++ b/src/job.c
|
|
Michal Schmidt |
bbee01 |
@@ -527,6 +527,7 @@ int job_finish_and_invalidate(Job *j, JobResult result) {
|
|
Michal Schmidt |
bbee01 |
Unit *other;
|
|
Michal Schmidt |
bbee01 |
JobType t;
|
|
Michal Schmidt |
bbee01 |
Iterator i;
|
|
Michal Schmidt |
bbee01 |
+ bool recursed = false;
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
assert(j);
|
|
Michal Schmidt |
bbee01 |
assert(j->installed);
|
|
Michal Schmidt |
bbee01 |
@@ -573,23 +574,29 @@ int job_finish_and_invalidate(Job *j, JobResult result) {
|
|
Michal Schmidt |
bbee01 |
if (other->meta.job &&
|
|
Michal Schmidt |
bbee01 |
(other->meta.job->type == JOB_START ||
|
|
Michal Schmidt |
bbee01 |
other->meta.job->type == JOB_VERIFY_ACTIVE ||
|
|
Michal Schmidt |
bbee01 |
- other->meta.job->type == JOB_RELOAD_OR_START))
|
|
Michal Schmidt |
bbee01 |
+ other->meta.job->type == JOB_RELOAD_OR_START)) {
|
|
Michal Schmidt |
bbee01 |
job_finish_and_invalidate(other->meta.job, JOB_DEPENDENCY);
|
|
Michal Schmidt |
bbee01 |
+ recursed = true;
|
|
Michal Schmidt |
bbee01 |
+ }
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
SET_FOREACH(other, u->meta.dependencies[UNIT_BOUND_BY], i)
|
|
Michal Schmidt |
bbee01 |
if (other->meta.job &&
|
|
Michal Schmidt |
bbee01 |
(other->meta.job->type == JOB_START ||
|
|
Michal Schmidt |
bbee01 |
other->meta.job->type == JOB_VERIFY_ACTIVE ||
|
|
Michal Schmidt |
bbee01 |
- other->meta.job->type == JOB_RELOAD_OR_START))
|
|
Michal Schmidt |
bbee01 |
+ other->meta.job->type == JOB_RELOAD_OR_START)) {
|
|
Michal Schmidt |
bbee01 |
job_finish_and_invalidate(other->meta.job, JOB_DEPENDENCY);
|
|
Michal Schmidt |
bbee01 |
+ recursed = true;
|
|
Michal Schmidt |
bbee01 |
+ }
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
|
|
Michal Schmidt |
bbee01 |
if (other->meta.job &&
|
|
Michal Schmidt |
bbee01 |
!other->meta.job->override &&
|
|
Michal Schmidt |
bbee01 |
(other->meta.job->type == JOB_START ||
|
|
Michal Schmidt |
bbee01 |
other->meta.job->type == JOB_VERIFY_ACTIVE ||
|
|
Michal Schmidt |
bbee01 |
- other->meta.job->type == JOB_RELOAD_OR_START))
|
|
Michal Schmidt |
bbee01 |
+ other->meta.job->type == JOB_RELOAD_OR_START)) {
|
|
Michal Schmidt |
bbee01 |
job_finish_and_invalidate(other->meta.job, JOB_DEPENDENCY);
|
|
Michal Schmidt |
bbee01 |
+ recursed = true;
|
|
Michal Schmidt |
bbee01 |
+ }
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
} else if (t == JOB_STOP) {
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
@@ -597,8 +604,10 @@ int job_finish_and_invalidate(Job *j, JobResult result) {
|
|
Michal Schmidt |
bbee01 |
if (other->meta.job &&
|
|
Michal Schmidt |
bbee01 |
(other->meta.job->type == JOB_START ||
|
|
Michal Schmidt |
bbee01 |
other->meta.job->type == JOB_VERIFY_ACTIVE ||
|
|
Michal Schmidt |
bbee01 |
- other->meta.job->type == JOB_RELOAD_OR_START))
|
|
Michal Schmidt |
bbee01 |
+ other->meta.job->type == JOB_RELOAD_OR_START)) {
|
|
Michal Schmidt |
bbee01 |
job_finish_and_invalidate(other->meta.job, JOB_DEPENDENCY);
|
|
Michal Schmidt |
bbee01 |
+ recursed = true;
|
|
Michal Schmidt |
bbee01 |
+ }
|
|
Michal Schmidt |
bbee01 |
}
|
|
Michal Schmidt |
bbee01 |
}
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
@@ -626,7 +635,7 @@ finish:
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
manager_check_finished(u->meta.manager);
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
- return 0;
|
|
Michal Schmidt |
bbee01 |
+ return recursed;
|
|
Michal Schmidt |
bbee01 |
}
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
int job_start_timer(Job *j) {
|
|
Michal Schmidt |
bbee01 |
diff --git a/src/manager.c b/src/manager.c
|
|
Michal Schmidt |
bbee01 |
index e626347..6d20258 100644
|
|
Michal Schmidt |
bbee01 |
--- a/src/manager.c
|
|
Michal Schmidt |
bbee01 |
+++ b/src/manager.c
|
|
Michal Schmidt |
bbee01 |
@@ -1214,13 +1214,18 @@ static int transaction_apply(Manager *m, JobMode mode) {
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
/* When isolating first kill all installed jobs which
|
|
Michal Schmidt |
bbee01 |
* aren't part of the new transaction */
|
|
Michal Schmidt |
bbee01 |
+ rescan:
|
|
Michal Schmidt |
bbee01 |
HASHMAP_FOREACH(j, m->jobs, i) {
|
|
Michal Schmidt |
bbee01 |
assert(j->installed);
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
if (hashmap_get(m->transaction_jobs, j->unit))
|
|
Michal Schmidt |
bbee01 |
continue;
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
- job_finish_and_invalidate(j, JOB_CANCELED);
|
|
Michal Schmidt |
bbee01 |
+ /* 'j' itself is safe to remove, but if other jobs
|
|
Michal Schmidt |
bbee01 |
+ are invalidated recursively, our iterator may become
|
|
Michal Schmidt |
bbee01 |
+ invalid and we need to start over. */
|
|
Michal Schmidt |
bbee01 |
+ if (job_finish_and_invalidate(j, JOB_CANCELED) > 0)
|
|
Michal Schmidt |
bbee01 |
+ goto rescan;
|
|
Michal Schmidt |
bbee01 |
}
|
|
Michal Schmidt |
bbee01 |
}
|
|
Michal Schmidt |
bbee01 |
|
|
Michal Schmidt |
bbee01 |
--
|
|
Michal Schmidt |
bbee01 |
1.7.4.4
|
|
Michal Schmidt |
bbee01 |
|