Part of the callback contract with check_all_finished() is that each running parallel task shall call it exactly once.
Previously, it was possible for stream_continue() or write_toolstack_record() to fail and call into check_all_finished(). As the save helpers callback has fired, it no longer counts as in use, which causes check_all_finished() to fire the stream callback. Then, unwinding the stack back and calling check_all_finished() a second time results in the same conditions being observed, and the stream callback being fired a second time. To avoid this, check_all_finished() is called before any other actions which continue the stream functionality, and the stream is only continued if it has not been torn down. This guarantees not to continue stream operations if the stream does not owe a callback to check_all_finished(). Signed-off-by: Andrew Cooper <andrew.coop...@citrix.com> --- CC: Ian Campbell <ian.campb...@citrix.com> CC: Ian Jackson <ian.jack...@eu.citrix.com> CC: Wei Liu <wei.l...@citrix.com> --- tools/libxl/libxl_stream_read.c | 14 ++++++++------ tools/libxl/libxl_stream_write.c | 5 +++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/libxl/libxl_stream_read.c b/tools/libxl/libxl_stream_read.c index 65100f4..3432933 100644 --- a/tools/libxl/libxl_stream_read.c +++ b/tools/libxl/libxl_stream_read.c @@ -738,14 +738,16 @@ void libxl__xc_domain_restore_done(libxl__egc *egc, void *dcs_void, goto err; } - /* - * Libxc has indicated that it is done with the stream. Resume reading - * libxl records from it. - */ - stream_continue(egc, stream); - err: check_all_finished(egc, stream, rc); + + if (libxl__stream_read_inuse(stream)) { + /* + * Libxc has indicated that it is done with the stream. Resume reading + * libxl records from it. + */ + stream_continue(egc, stream); + } } static void conversion_done(libxl__egc *egc, diff --git a/tools/libxl/libxl_stream_write.c b/tools/libxl/libxl_stream_write.c index 676ad0a..44f8b2f 100644 --- a/tools/libxl/libxl_stream_write.c +++ b/tools/libxl/libxl_stream_write.c @@ -275,10 +275,11 @@ void libxl__xc_domain_save_done(libxl__egc *egc, void *dss_void, goto err; } - write_toolstack_record(egc, stream); - err: check_all_finished(egc, stream, rc); + + if (libxl__stream_write_inuse(stream)) + write_toolstack_record(egc, stream); } static void write_toolstack_record(libxl__egc *egc, -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel