discover: don't free cancelled load tasks
authorJeremy Kerr <jk@ozlabs.org>
Thu, 22 May 2014 10:42:33 +0000 (18:42 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Thu, 22 May 2014 12:54:53 +0000 (20:54 +0800)
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>
discover/boot.c

index e5803a76dcf0fbc228f2c426b19c415c28d382ef..ce9c1e099f071d51245b8610e90db514fcb7a29b 100644 (file)
@@ -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;
                } 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;
                }
        }
 
                }
        }