From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Cooper Subject: Re: [PATCH v2 for-4.6 3/3] tools/libxl: Only continue stream operations if the stream is still in progress Date: Tue, 28 Jul 2015 14:56:49 +0100 Message-ID: <55B78A21.3070402@citrix.com> References: <1438015647-25377-1-git-send-email-andrew.cooper3@citrix.com> <1438015647-25377-4-git-send-email-andrew.cooper3@citrix.com> <21943.34423.586101.713988@mariner.uk.xensource.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <21943.34423.586101.713988@mariner.uk.xensource.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Ian Jackson Cc: Wei Liu , Ian Campbell , Xen-devel List-Id: xen-devel@lists.xenproject.org On 28/07/15 14:41, Ian Jackson wrote: > Andrew Cooper writes ("[PATCH v2 for-4.6 3/3] tools/libxl: Only continue stream operations if the stream is still in progress"): >> Part of the callback contract with check_all_finished() is that each >> running parallel task shall call it exactly once. > ... >> @@ -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 re\ > ading >> + * libxl records from it. >> + */ >> + stream_continue(egc, stream); >> + } > This doesn't look convincing to me. (Also, wrap damage in the > comment.) It may be possible to prove that it's not buggy, but it's > certainly confusing. In general the the which sets up the next > callback should be at the end of functions, because that way > reentrancy hazards are more easily seen to be avoided. > > Why not just do this: > > /* > * Libxc has indicated that it is done with the stream. Resume reading > * libxl records from it. > */ > stream_continue(egc, stream); > + return; > > err: > check_all_finished(egc, stream, rc); > > ? > > And the same in the next one. That was my first attempt to fix this issue (as observed in v1), but it is buggy. libxl__xc_domain_restore_done() is required to call check_all_finished() exactly once, as part of its callback contract. Imagine a scenario whereby some error has occured and check_all_finished() has _abort()'ed the tasks, but the save helper was already on the way out, signalling success. In such a case, we would both omit the check_all_finished() call, thus omitting the eventual stream callback, and start a further action on a now-defunct stream. It is only save to stream_continue() if the stream is currently in use, which is not a guaranteed situation in this function even if rc is 0. ~Andrew