discover: Add load_url_cancel
authorJeremy Kerr <jk@ozlabs.org>
Mon, 14 Oct 2013 05:10:38 +0000 (13:10 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Mon, 14 Oct 2013 07:27:11 +0000 (15:27 +0800)
We'd like a way to cancel pending loads, as part of aborting the boot
process.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
discover/paths.c
discover/paths.h

index c352ca02e4e214f2607b32abbc6a00857e7056c4..aa977fdba1f3d0bcbdbf84356a854877c202a17d 100644 (file)
@@ -1,5 +1,6 @@
 #define _GNU_SOURCE
 
+#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -79,9 +80,14 @@ static void load_url_process_exit(struct process *process)
        data = task->async_data;
        cb = task->async_cb;
 
-       result->status = process->exit_status == 0 ? LOAD_OK : LOAD_ERROR;
-       if (result->status == LOAD_ERROR)
+       if (result->status == LOAD_CANCELLED) {
                load_url_result_cleanup_local(result);
+       } else if (process->exit_status == 0) {
+               result->status = LOAD_OK;
+       } else {
+               result->status = LOAD_ERROR;
+               load_url_result_cleanup_local(result);
+       }
 
        /* The load callback may well free the ctx, which was the
         * talloc parent of the task. Therefore, we want to do our cleanup
@@ -89,6 +95,7 @@ static void load_url_process_exit(struct process *process)
         */
        process_release(process);
        talloc_free(task);
+       result->task = NULL;
 
        cb(result, data);
 }
@@ -359,6 +366,7 @@ struct load_url_result *load_url_async(void *ctx, struct pb_url *url,
        task->url = url;
        task->async = async_cb != NULL;
        task->result = talloc_zero(ctx, struct load_url_result);
+       task->result->task = task;
        task->process = process_create(task);
        if (task->async) {
                task->async_cb = async_cb;
@@ -407,3 +415,22 @@ struct load_url_result *load_url(void *ctx, struct pb_url *url)
 {
        return load_url_async(ctx, url, NULL, NULL);
 }
+
+void load_url_async_cancel(struct load_url_result *res)
+{
+       struct load_task *task = res->task;
+
+       /* the completion callback may have already been called; this clears
+        * res->task */
+       if (!task)
+               return;
+
+       if (res->status == LOAD_CANCELLED)
+               return;
+
+       assert(task->async);
+       assert(task->process);
+
+       res->status = LOAD_CANCELLED;
+       process_stop_async(task->process);
+}
index e905094d566d9a25b702bef3445c1ab6c64958fa..ed0e153f88a63c169c66308811db10e8d1c6793b 100644 (file)
@@ -16,6 +16,7 @@ char *join_paths(void *alloc_ctx, const char *a, const char *b);
  */
 const char *mount_base(void);
 
+struct load_task;
 
 struct load_url_result {
        enum {
@@ -26,9 +27,12 @@ struct load_url_result {
                             * (sync will see a NULL result) */
 
                LOAD_ASYNC, /* async load still in progress */
+
+               LOAD_CANCELLED,
        } status;
-       const char      *local;
-       bool            cleanup_local;
+       const char              *local;
+       bool                    cleanup_local;
+       struct load_task        *task;
 };
 
 /* callback type for asynchronous loads. The callback implementation is
@@ -40,6 +44,9 @@ typedef void (*load_url_complete)(struct load_url_result *result, void *data);
 struct load_url_result *load_url_async(void *ctx, struct pb_url *url,
                load_url_complete complete, void *data);
 
+/* Cancel a pending load */
+void load_url_async_cancel(struct load_url_result *res);
+
 struct load_url_result *load_url(void *ctx, struct pb_url *url);
 
 #endif /* PATHS_H */