The libxl__spawn_spawn internal API permits the caller to specify .timeout_ms==-1, meaning to wait forever. Provide an explicit cancellable to allow spawns to be cancelled.
I think there are not currently any internal callers which do use spawn with an infinite timeout, but this should not be left as a lacuna for later. Also, this change means that in practice anything which is cancelled while spawning ought to be queued for two cancellation notifications: one from its timeout, and one from the explicit cancellation registration. Hopefully this will mean that more exciting paths are exercised during testing. Signed-off-by: Ian Jackson <ian.jack...@eu.citrix.com> --- v2: New in this version of the series. --- tools/libxl/libxl_exec.c | 17 +++++++++++++++++ tools/libxl/libxl_internal.h | 1 + 2 files changed, 18 insertions(+) diff --git a/tools/libxl/libxl_exec.c b/tools/libxl/libxl_exec.c index 478b4c2..c005b7d 100644 --- a/tools/libxl/libxl_exec.c +++ b/tools/libxl/libxl_exec.c @@ -261,6 +261,7 @@ static void spawn_watch_event(libxl__egc *egc, libxl__xswait_state *xswa, int rc, const char *xsdata); static void spawn_middle_death(libxl__egc *egc, libxl__ev_child *childw, pid_t pid, int status); +static void spawn_cancel(libxl__egc *egc, libxl__ao_cancellable *, int rc); /* Precondition: Partial. Results: Idle. */ static void spawn_cleanup(libxl__gc *gc, libxl__spawn_state *ss); @@ -273,6 +274,7 @@ void libxl__spawn_init(libxl__spawn_state *ss) { libxl__ev_child_init(&ss->mid); libxl__xswait_init(&ss->xswait); + libxl__ao_cancellable_init(&ss->cancel); } int libxl__spawn_spawn(libxl__egc *egc, libxl__spawn_state *ss) @@ -285,6 +287,10 @@ int libxl__spawn_spawn(libxl__egc *egc, libxl__spawn_state *ss) libxl__spawn_init(ss); ss->failed = ss->detaching = 0; + ss->cancel.ao = ao; + ss->cancel.callback = spawn_cancel; + rc = libxl__ao_cancellable_register(&ss->cancel); + ss->xswait.ao = ao; ss->xswait.what = GCSPRINTF("%s startup", ss->what); ss->xswait.path = ss->xspath; @@ -347,6 +353,7 @@ int libxl__spawn_spawn(libxl__egc *egc, libxl__spawn_state *ss) static void spawn_cleanup(libxl__gc *gc, libxl__spawn_state *ss) { assert(!libxl__ev_child_inuse(&ss->mid)); + libxl__ao_cancellable_deregister(&ss->cancel); libxl__xswait_stop(gc, &ss->xswait); } @@ -382,6 +389,16 @@ static void spawn_fail(libxl__egc *egc, libxl__spawn_state *ss) spawn_detach(gc, ss); } +static void spawn_cancel(libxl__egc *egc, libxl__ao_cancellable *cancel, + int rc) +{ + EGC_GC; + libxl__spawn_state *ss = CONTAINER_OF(cancel, *ss, cancel); + + LOG(NOTICE, "%s: spawn cancelled", ss->what); + spawn_fail(egc, ss); +} + static void spawn_watch_event(libxl__egc *egc, libxl__xswait_state *xswa, int rc, const char *p) { diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 790a489..a251b43 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1418,6 +1418,7 @@ struct libxl__spawn_state { int detaching; /* we are in Detaching */ int failed; /* might be true whenever we are not Idle */ libxl__ev_child mid; /* always in use whenever we are not Idle */ + libxl__ao_cancellable cancel; /* in case timeout was -1 */ libxl__xswait_state xswait; }; -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel