diff options
author | Lennart Poettering <lennart@poettering.net> | 2010-08-13 19:29:21 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2010-08-13 19:29:21 +0200 |
commit | 2cf19a7a8f42a313234b716eeefe08bdf77af348 (patch) | |
tree | ee0efb738c837c4000eb2296acd082efe3c7b6b1 | |
parent | 3cc144eba3b085265d1620c441e38f759e204716 (diff) |
job: don't accidently access a job that doesn't exist anymore
-rw-r--r-- | src/job.c | 25 |
1 files changed, 18 insertions, 7 deletions
@@ -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; } |