summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-08-13 19:29:21 +0200
committerLennart Poettering <lennart@poettering.net>2010-08-13 19:29:21 +0200
commit2cf19a7a8f42a313234b716eeefe08bdf77af348 (patch)
treeee0efb738c837c4000eb2296acd082efe3c7b6b1
parent3cc144eba3b085265d1620c441e38f759e204716 (diff)
job: don't accidently access a job that doesn't exist anymore
-rw-r--r--src/job.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/job.c b/src/job.c
index d7082153de..5d4a092345 100644
--- a/src/job.c
+++ b/src/job.c
@@ -353,6 +353,8 @@ bool job_is_runnable(Job *j) {
int job_run_and_invalidate(Job *j) {
int r;
+ uint32_t id;
+ Manager *m;
assert(j);
assert(j->installed);
@@ -371,6 +373,14 @@ int job_run_and_invalidate(Job *j) {
j->state = JOB_RUNNING;
job_add_to_dbus_queue(j);
+ /* While we execute this operation the job might go away (for
+ * example: because it is replaced by a new, conflicting
+ * job.) To make sure we don't access a freed job later on we
+ * store the id here, so that we can verify the job is still
+ * valid. */
+ id = j->id;
+ m = j->manager;
+
switch (j->type) {
case JOB_START:
@@ -431,13 +441,14 @@ int job_run_and_invalidate(Job *j) {
assert_not_reached("Unknown job type");
}
- if (r == -EALREADY)
- r = job_finish_and_invalidate(j, true);
- else if (r == -EAGAIN) {
- j->state = JOB_WAITING;
- return -EAGAIN;
- } else if (r < 0)
- r = job_finish_and_invalidate(j, false);
+ if ((j = manager_get_job(m, id))) {
+ if (r == -EALREADY)
+ r = job_finish_and_invalidate(j, true);
+ else if (r == -EAGAIN)
+ j->state = JOB_WAITING;
+ else if (r < 0)
+ r = job_finish_and_invalidate(j, false);
+ }
return r;
}