From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Kevin Wolf" <kwolf@redhat.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Thomas Huth" <thuth@redhat.com>,
"Vladimir Sementsov-Ogievskiy" <vsementsov@virtuozzo.com>,
"Daniel Berrange" <berrange@redhat.com>,
"Eduardo Habkost" <ehabkost@redhat.com>,
qemu-block@nongnu.org, "Alex Bennée" <alex.bennee@linaro.org>,
"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
"Wainer dos Santos Moschetta" <wainersm@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
"Willian Rampazzo" <willianr@redhat.com>,
"Hanna Reitz" <hreitz@redhat.com>,
"Cleber Rosa" <crosa@redhat.com>, "John Snow" <jsnow@redhat.com>
Subject: [PULL 1/5] python/aqmp: Fix disconnect during capabilities negotiation
Date: Tue, 16 Nov 2021 19:33:13 -0500 [thread overview]
Message-ID: <20211117003317.2844087-2-jsnow@redhat.com> (raw)
In-Reply-To: <20211117003317.2844087-1-jsnow@redhat.com>
If we receive ConnectionResetError (ECONNRESET) while attempting to
perform capabilities negotiation -- prior to the establishment of the
async reader/writer tasks -- the disconnect function is not aware that
we are in an error pathway.
As a result, when attempting to close the StreamWriter, we'll see the
same ConnectionResetError that caused us to initiate a disconnect in the
first place, which will cause the disconnect task itself to fail, which
emits a CRITICAL logging event.
I still don't know if there's a smarter way to check to see if an
exception received at this point is "the same" exception as the one that
caused the initial disconnect, but for now the problem can be avoided by
improving the error pathway detection in the exit path.
Reported-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Tested-by: Thomas Huth <thuth@redhat.com>
Message-id: 20211111143719.2162525-2-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
---
python/qemu/aqmp/protocol.py | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/python/qemu/aqmp/protocol.py b/python/qemu/aqmp/protocol.py
index ae1df24026..860b79512d 100644
--- a/python/qemu/aqmp/protocol.py
+++ b/python/qemu/aqmp/protocol.py
@@ -623,13 +623,21 @@ async def _bh_disconnect(self) -> None:
def _done(task: Optional['asyncio.Future[Any]']) -> bool:
return task is not None and task.done()
- # NB: We can't rely on _bh_tasks being done() here, it may not
- # yet have had a chance to run and gather itself.
+ # Are we already in an error pathway? If either of the tasks are
+ # already done, or if we have no tasks but a reader/writer; we
+ # must be.
+ #
+ # NB: We can't use _bh_tasks to check for premature task
+ # completion, because it may not yet have had a chance to run
+ # and gather itself.
tasks = tuple(filter(None, (self._writer_task, self._reader_task)))
error_pathway = _done(self._reader_task) or _done(self._writer_task)
+ if not tasks:
+ error_pathway |= bool(self._reader) or bool(self._writer)
try:
- # Try to flush the writer, if possible:
+ # Try to flush the writer, if possible.
+ # This *may* cause an error and force us over into the error path.
if not error_pathway:
await self._bh_flush_writer()
except BaseException as err:
@@ -639,7 +647,7 @@ def _done(task: Optional['asyncio.Future[Any]']) -> bool:
self.logger.debug("%s:\n%s\n", emsg, pretty_traceback())
raise
finally:
- # Cancel any still-running tasks:
+ # Cancel any still-running tasks (Won't raise):
if self._writer_task is not None and not self._writer_task.done():
self.logger.debug("Cancelling writer task.")
self._writer_task.cancel()
@@ -652,7 +660,7 @@ def _done(task: Optional['asyncio.Future[Any]']) -> bool:
self.logger.debug("Waiting for tasks to complete ...")
await asyncio.wait(tasks)
- # Lastly, close the stream itself. (May raise):
+ # Lastly, close the stream itself. (*May raise*!):
await self._bh_close_stream(error_pathway)
self.logger.debug("Disconnected.")
--
2.31.1
next prev parent reply other threads:[~2021-11-17 0:36 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-17 0:33 [PULL 0/5] Python patches John Snow
2021-11-17 0:33 ` John Snow [this message]
2021-11-17 0:33 ` [PULL 2/5] python/aqmp: fix ConnectError string method John Snow
2021-11-17 0:33 ` [PULL 3/5] scripts/device-crash-test: simplify Exception handling John Snow
2021-11-17 0:33 ` [PULL 4/5] scripts/device-crash-test: don't emit AQMP connection errors to stdout John Snow
2021-11-17 0:33 ` [PULL 5/5] scripts/device-crash-test: hide tracebacks for QMP connect errors John Snow
2021-11-17 8:47 ` [PULL 0/5] Python patches Richard Henderson
2021-11-17 9:41 ` Gerd Hoffmann
2021-11-17 17:56 ` John Snow
2021-11-17 18:20 ` Vladimir Sementsov-Ogievskiy
2021-11-17 19:07 ` John Snow
2021-11-17 19:12 ` Vladimir Sementsov-Ogievskiy
2021-11-18 6:45 ` Gerd Hoffmann
2021-11-18 15:50 ` John Snow
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211117003317.2844087-2-jsnow@redhat.com \
--to=jsnow@redhat.com \
--cc=alex.bennee@linaro.org \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=crosa@redhat.com \
--cc=ehabkost@redhat.com \
--cc=f4bug@amsat.org \
--cc=hreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=thuth@redhat.com \
--cc=vsementsov@virtuozzo.com \
--cc=wainersm@redhat.com \
--cc=willianr@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).