diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2014-05-22 18:42:33 +0800 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2014-05-22 20:54:53 +0800 |
commit | 1d69ceee0b8fac1f4451a75b6e4b14ee2d5d91dc (patch) | |
tree | 47ce4e027f3a1b73b04391a3e34dd23f2ac67b07 /discover/boot.c | |
parent | 1ae17ad22c1d111e35d75d4e93d609efd61b5329 (diff) | |
download | talos-petitboot-1d69ceee0b8fac1f4451a75b6e4b14ee2d5d91dc.tar.gz talos-petitboot-1d69ceee0b8fac1f4451a75b6e4b14ee2d5d91dc.zip |
discover: don't free cancelled load tasks
Currently, we have a bug when a boot task with more than one load tasks
is cancelled:
1) boot_cancel calls cleanup_cancellations, which performs a
load_url_async_cancel on all load tasks. This sets the load tasks'
states to LOAD_CANCELLED, and signals associated processes.
2) The first load task process completes, we get a load_url_process_exit
callback. This then invokes cleanup_cancellations.
3) cleanup_cancellations then (incorrectly) frees the boot task (and
hence freeing all pending load tasks) as no load tasks are in LOAD_ASYNC
state (we set them all to LOAD_CANCELLED in step 1)
4) The actual completion for the second load task attempts to reference
the now-freed task structure.
This change fixes the issue by handing the LOAD_CANCELLED state properly
- if we find a load task in this state, we consider the boot task still
pending, and delay the free until all loads are complete.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'discover/boot.c')
-rw-r--r-- | discover/boot.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/discover/boot.c b/discover/boot.c index e5803a7..ce9c1e0 100644 --- a/discover/boot.c +++ b/discover/boot.c @@ -340,6 +340,11 @@ static void cleanup_cancellations(struct boot_task *task, } else if (result->status == LOAD_ASYNC) { load_url_async_cancel(result); pending = true; + + /* if we're waiting for a cancellation, we still need to + * wait for the completion before freeing the boot task */ + } else if (result->status == LOAD_CANCELLED) { + pending = true; } } |