Commit 2cf19a7a authored by Lennart Poettering's avatar Lennart Poettering
Browse files

job: don't accidently access a job that doesn't exist anymore

parent 3cc144eb
...@@ -353,6 +353,8 @@ bool job_is_runnable(Job *j) { ...@@ -353,6 +353,8 @@ bool job_is_runnable(Job *j) {
int job_run_and_invalidate(Job *j) { int job_run_and_invalidate(Job *j) {
int r; int r;
uint32_t id;
Manager *m;
assert(j); assert(j);
assert(j->installed); assert(j->installed);
...@@ -371,6 +373,14 @@ int job_run_and_invalidate(Job *j) { ...@@ -371,6 +373,14 @@ int job_run_and_invalidate(Job *j) {
j->state = JOB_RUNNING; j->state = JOB_RUNNING;
job_add_to_dbus_queue(j); 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) { switch (j->type) {
case JOB_START: case JOB_START:
...@@ -431,13 +441,14 @@ int job_run_and_invalidate(Job *j) { ...@@ -431,13 +441,14 @@ int job_run_and_invalidate(Job *j) {
assert_not_reached("Unknown job type"); assert_not_reached("Unknown job type");
} }
if (r == -EALREADY) if ((j = manager_get_job(m, id))) {
r = job_finish_and_invalidate(j, true); if (r == -EALREADY)
else if (r == -EAGAIN) { r = job_finish_and_invalidate(j, true);
j->state = JOB_WAITING; else if (r == -EAGAIN)
return -EAGAIN; j->state = JOB_WAITING;
} else if (r < 0) else if (r < 0)
r = job_finish_and_invalidate(j, false); r = job_finish_and_invalidate(j, false);
}
return r; return r;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment