diff --git a/tools/libxl/libxl_aoutils.c b/tools/libxl/libxl_aoutils.c index 450caae41c..593a5754e5 100644 --- a/tools/libxl/libxl_aoutils.c +++ b/tools/libxl/libxl_aoutils.c @@ -80,12 +80,13 @@ void xswait_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *xsw, } void xswait_timeout_callback(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs) + const struct timeval *requested_abs, + int rc) { EGC_GC; libxl__xswait_state *xswa = CONTAINER_OF(ev, *xswa, time_ev); LOG(DEBUG, "%s: xswait timeout (path=%s)", xswa->what, xswa->path); - xswait_report_error(egc, xswa, ERROR_TIMEDOUT); + xswait_report_error(egc, xswa, rc); } static void xswait_report_error(libxl__egc *egc, libxl__xswait_state *xswa, @@ -506,11 +507,15 @@ int libxl__openptys(libxl__openpty_state *op, static void async_exec_timeout(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs) + const struct timeval *requested_abs, + int rc) { libxl__async_exec_state *aes = CONTAINER_OF(ev, *aes, time); STATE_AO_GC(aes->ao); + if (!aes->rc) + aes->rc = rc; + libxl__ev_time_deregister(gc, &aes->time); assert(libxl__ev_child_inuse(&aes->child)); diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c index 012a9f8725..82096294be 100644 --- a/tools/libxl/libxl_device.c +++ b/tools/libxl/libxl_device.c @@ -717,7 +717,7 @@ out: /* This callback is part of the Qemu devices Badge */ static void device_qemu_timeout(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs); + const struct timeval *requested_abs, int rc); static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds, int rc); @@ -880,7 +880,7 @@ out: } static void device_qemu_timeout(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs) + const struct timeval *requested_abs, int rc) { libxl__ao_device *aodev = CONTAINER_OF(ev, *aodev, timeout); STATE_AO_GC(aodev->ao); @@ -888,7 +888,9 @@ static void device_qemu_timeout(libxl__egc *egc, libxl__ev_time *ev, char *state_path = GCSPRINTF("%s/state", be_path); const char *xs_state; xs_transaction_t t = 0; - int rc = 0; + + if (rc != ERROR_TIMEDOUT) + goto out; libxl__ev_time_deregister(gc, &aodev->timeout); diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index 40a2d79b33..b081ef7af5 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -1162,7 +1162,8 @@ static void domain_suspend_callback_common_done(libxl__egc *egc, */ static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs); + const struct timeval *requested_abs, + int rc); static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch*, const char *watch_path, const char *event_path); static void switch_logdirty_done(libxl__egc *egc, @@ -1289,7 +1290,8 @@ void libxl__domain_suspend_common_switch_qemu_logdirty } } static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs) + const struct timeval *requested_abs, + int rc) { libxl__domain_suspend_state *dss = CONTAINER_OF(ev, *dss, logdirty.timeout); STATE_AO_GC(dss->ao); @@ -1438,7 +1440,7 @@ static void suspend_common_wait_guest_watch(libxl__egc *egc, static void suspend_common_wait_guest_check(libxl__egc *egc, libxl__domain_suspend_state *dss); static void suspend_common_wait_guest_timeout(libxl__egc *egc, - libxl__ev_time *ev, const struct timeval *requested_abs); + libxl__ev_time *ev, const struct timeval *requested_abs, int rc); static void domain_suspend_common_done(libxl__egc *egc, libxl__domain_suspend_state *dss, @@ -1672,12 +1674,15 @@ static void suspend_common_wait_guest_check(libxl__egc *egc, } static void suspend_common_wait_guest_timeout(libxl__egc *egc, - libxl__ev_time *ev, const struct timeval *requested_abs) + libxl__ev_time *ev, const struct timeval *requested_abs, int rc) { libxl__domain_suspend_state *dss = CONTAINER_OF(ev, *dss, guest_timeout); STATE_AO_GC(dss->ao); - LOG(ERROR, "guest did not suspend, timed out"); - domain_suspend_common_done(egc, dss, ERROR_GUEST_TIMEDOUT); + if (rc == ERROR_TIMEDOUT) { + LOG(ERROR, "guest did not suspend, timed out"); + rc = ERROR_GUEST_TIMEDOUT; + } + domain_suspend_common_done(egc, dss, rc); } static void domain_suspend_common_guest_suspended(libxl__egc *egc, @@ -1929,7 +1934,8 @@ static void remus_devices_commit_cb(libxl__egc *egc, libxl__remus_devices_state *rds, int rc); static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs); + const struct timeval *requested_abs, + int rc); static void libxl__remus_domain_checkpoint_callback(void *data) { @@ -2004,7 +2010,8 @@ out: } static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs) + const struct timeval *requested_abs, + int rc) { libxl__domain_suspend_state *dss = CONTAINER_OF(ev, *dss, checkpoint_timeout); @@ -2016,7 +2023,11 @@ static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev, * (xc_domain_save.c). in order to continue executing the infinite loop * (suspend, checkpoint, resume) in xc_domain_save(). */ - libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 1); + + if (rc) + dss->rc = rc; + + libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, !rc); } /*----- main code for suspending, in order of execution -----*/ diff --git a/tools/libxl/libxl_event.c b/tools/libxl/libxl_event.c index 217fe974e1..2809743c8a 100644 --- a/tools/libxl/libxl_event.c +++ b/tools/libxl/libxl_event.c @@ -406,7 +406,7 @@ void libxl__ev_time_deregister(libxl__gc *gc, libxl__ev_time *ev) return; } -static void time_occurs(libxl__egc *egc, libxl__ev_time *etime) +static void time_occurs(libxl__egc *egc, libxl__ev_time *etime, int rc) { DBG("ev_time=%p occurs abs=%lu.%06lu", etime, (unsigned long)etime->abs.tv_sec, @@ -414,7 +414,7 @@ static void time_occurs(libxl__egc *egc, libxl__ev_time *etime) libxl__ev_time_callback *func = etime->func; etime->func = 0; - func(egc, etime, &etime->abs); + func(egc, etime, &etime->abs, rc); } @@ -1207,7 +1207,7 @@ static void afterpoll_internal(libxl__egc *egc, libxl__poller *poller, time_deregister(gc, etime); - time_occurs(egc, etime); + time_occurs(egc, etime, ERROR_TIMEDOUT); } } @@ -1274,7 +1274,7 @@ void libxl_osevent_occurred_timeout(libxl_ctx *ctx, void *for_libxl) LIBXL_TAILQ_REMOVE(&CTX->etimes, ev, entry); - time_occurs(egc, ev); + time_occurs(egc, ev, ERROR_TIMEDOUT); out: CTX_UNLOCK; diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 5b63e84701..d4617e4daa 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -195,7 +195,8 @@ struct libxl__ev_fd { typedef struct libxl__ev_time libxl__ev_time; typedef void libxl__ev_time_callback(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs); + const struct timeval *requested_abs, + int rc); /* TIMEDOUT or ABORTED */ struct libxl__ev_time { /* caller should include this in their own struct */ /* read-only for caller, who may read only when registered: */ @@ -1134,13 +1135,13 @@ typedef struct libxl__xswait_state libxl__xswait_state; * Otherwise, xswait will continue waiting and watching and * will call you back later. * - * rc==ERROR_TIMEDOUT + * rc==ERROR_TIMEDOUT, rc==ERROR_ABORTED * * The specified timeout was reached. * This has NOT been logged (except to the debug log). * xswait will not continue (but calling libxl__xswait_stop is OK). * - * rc!=0, !=ERROR_TIMEDOUT + * rc!=0, !=ERROR_TIMEDOUT, !=ERROR_ABORTED * * Some other error occurred. * This HAS been logged. @@ -1180,8 +1181,9 @@ int libxl__xswait_start(libxl__gc*, libxl__xswait_state*); typedef struct libxl__ev_devstate libxl__ev_devstate; typedef void libxl__ev_devstate_callback(libxl__egc *egc, libxl__ev_devstate*, int rc); - /* rc will be 0, ERROR_TIMEDOUT, ERROR_INVAL (meaning path was removed), - * or ERROR_FAIL if other stuff went wrong (in which latter case, logged) */ + /* rc will be 0, ERROR_TIMEDOUT, ERROR_ABORTED, ERROR_INVAL + * (meaning path was removed), or ERROR_FAIL if other stuff went + * wrong (in which latter case, logged) */ struct libxl__ev_devstate { /* read-only for caller, who may read only when waiting: */ diff --git a/tools/libxl/libxl_test_timedereg.c b/tools/libxl/libxl_test_timedereg.c index e2cc27d9e5..c464663487 100644 --- a/tools/libxl/libxl_test_timedereg.c +++ b/tools/libxl/libxl_test_timedereg.c @@ -28,7 +28,7 @@ static libxl__ao *tao; static int seq; static void occurs(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs); + const struct timeval *requested_abs, int rc); static void regs(libxl__ao *ao, int j) { @@ -59,13 +59,15 @@ int libxl_test_timedereg(libxl_ctx *ctx, libxl_asyncop_how *ao_how) } static void occurs(libxl__egc *egc, libxl__ev_time *ev, - const struct timeval *requested_abs) + const struct timeval *requested_abs, int rc) { EGC_GC; int i; int off = ev - &et[0][0]; - LOG(DEBUG,"occurs[%d][%d] seq=%d", off/NTIMES, off%NTIMES, seq); + LOG(DEBUG,"occurs[%d][%d] seq=%d rc=%d", off/NTIMES, off%NTIMES, seq, rc); + + assert(!rc); switch (seq) { case 0: