From: "Niteesh G. S." <niteesh.gs@gmail.com>
To: John Snow <jsnow@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
qemu-devel <qemu-devel@nongnu.org>,
Wainer dos Santos Moschetta <wainersm@redhat.com>,
Markus Armbruster <armbru@redhat.com>,
Willian Rampazzo <wrampazz@redhat.com>,
Cleber Rosa <crosa@redhat.com>, Eric Blake <eblake@redhat.com>
Subject: Re: [PATCH v2 00/24] python: introduce Asynchronous QMP package
Date: Thu, 22 Jul 2021 01:32:39 +0530 [thread overview]
Message-ID: <CAN6ztm9tgh=MsrYDBBi9ZcUCWabL+NKf9WeqKJO2e9HB6oHedg@mail.gmail.com> (raw)
In-Reply-To: <CAFn=p-YgJTWYm5-XNbQMKB2wn33Lrd2wbFRtpPeW0GTakSR0AA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 7434 bytes --]
On Thu, Jul 22, 2021 at 1:25 AM John Snow <jsnow@redhat.com> wrote:
> Looping qemu-devel back in: I removed them by accident by not hitting
> reply-all :(
>
> On Wed, Jul 21, 2021 at 2:06 PM Niteesh G. S. <niteesh.gs@gmail.com>
> wrote:
>
>>
>>
>> On Wed, Jul 21, 2021 at 11:03 PM John Snow <jsnow@redhat.com> wrote:
>>
>>>
>>>
>>> On Wed, Jul 21, 2021 at 1:04 PM Niteesh G. S. <niteesh.gs@gmail.com>
>>> wrote:
>>>
>>>> Hello all,
>>>>
>>>> I recently rebased(incrementally) my TUI on this V2 patch and faced an
>>>> issue.
>>>> https://gitlab.com/niteesh.gs/qemu/-/commits/aqmp-tui-prototype-v3
>>>> I decided to rebase incrementally so that I can address some of the
>>>> comments posted
>>>> in my patch series. While testing out, the initial draft of TUI
>>>> which worked fine in the V1
>>>> version of AQMP failed in this version.
>>>>
>>>> Disconnecting from a fully connected state doesn't exit cleanly.
>>>>
>>>> ---------------------------------------------------------------------------------
>>>> To reproduce the issue:
>>>> 1) Initiate a QMP server
>>>>
>>>
>>> Please provide the command line.
>>>
>> qemu-system-x86_64 -qmp tcp:localhost:1234,server,wait=on
>>
>>>
>>>
>>>> 2) Connect the TUI to the server using aqmp-tui localhost:1234
>>>> --log-file log.txt
>>>>
>>>
>>> The entry point isn't defined yet in your series, so I will assume
>>> "python3 -m qemu.aqmp.aqmp_tui localhost:1234" should work here.
>>>
>> Yup, sorry about that. I realized this later when recreated the venv.
>>
>>>
>>>
>>>> 3) Once the TUI is connected and running, press 'Esc' to exit the app.
>>>> This should result
>>>> in the following exception.
>>>>
>>>> --------------------------------------------------------------------------------------------------------------------------------------------
>>>> Transitioning from 'Runstate.IDLE' to 'Runstate.CONNECTING'.
>>>> Connecting to ('localhost', 1234) ...
>>>> Connected.
>>>> Awaiting greeting ...
>>>> Response: {
>>>> "QMP": {
>>>> .......... Skipping
>>>> }
>>>> }
>>>> Negotiating capabilities ...
>>>> Request: {
>>>> "execute": "qmp_capabilities",
>>>> .......... Skipping
>>>> }
>>>> }
>>>> Response: {
>>>> "return": {}
>>>> }
>>>> Transitioning from 'Runstate.CONNECTING' to 'Runstate.RUNNING'.
>>>> Transitioning from 'Runstate.RUNNING' to 'Runstate.DISCONNECTING'.
>>>> Scheduling disconnect.
>>>> Draining the outbound queue ...
>>>> Flushing the StreamWriter ...
>>>> Cancelling writer task ...
>>>> Task.Writer: cancelled.
>>>> Task.Writer: exiting.
>>>> Cancelling reader task ...
>>>> Task.Reader: cancelled.
>>>> Task.Reader: exiting.
>>>> Closing StreamWriter.
>>>> Waiting for StreamWriter to close ...
>>>> QMP Disconnected.
>>>> Transitioning from 'Runstate.DISCONNECTING' to 'Runstate.IDLE'.
>>>> _kill_app: Connection lost
>>>> Connection lost
>>>> | Traceback (most recent call last):
>>>> | File
>>>> "/home/niteesh/development/qemu/python/qemu/aqmp/aqmp_tui.py", line 246, in
>>>> run
>>>> | main_loop.run()
>>>> | File
>>>> "/home/niteesh/development/qemu/python/.venv/lib/python3.6/site-packages/urwid/main_loop.py",
>>>> line 287, in run
>>>> | self._run()
>>>> | File
>>>> "/home/niteesh/development/qemu/python/.venv/lib/python3.6/site-packages/urwid/main_loop.py",
>>>> line 385, in _run
>>>> | self.event_loop.run()
>>>> | File
>>>> "/home/niteesh/development/qemu/python/.venv/lib/python3.6/site-packages/urwid/main_loop.py",
>>>> line 1494, in run
>>>> | reraise(*exc_info)
>>>> | File
>>>> "/home/niteesh/development/qemu/python/.venv/lib/python3.6/site-packages/urwid/compat.py",
>>>> line 58, in reraise
>>>> | raise value
>>>> | File
>>>> "/home/niteesh/development/qemu/python/qemu/aqmp/aqmp_tui.py", line 206, in
>>>> _kill_app
>>>> | raise err
>>>> | File
>>>> "/home/niteesh/development/qemu/python/qemu/aqmp/aqmp_tui.py", line 201, in
>>>> _kill_app
>>>> | await self.disconnect()
>>>> | File
>>>> "/home/niteesh/development/qemu/python/qemu/aqmp/protocol.py", line 303, in
>>>> disconnect
>>>> | await self._wait_disconnect()
>>>> | File
>>>> "/home/niteesh/development/qemu/python/qemu/aqmp/protocol.py", line 573, in
>>>> _wait_disconnect
>>>> | await self._dc_task
>>>> | File
>>>> "/home/niteesh/development/qemu/python/qemu/aqmp/qmp_client.py", line 316,
>>>> in _bh_disconnect
>>>> | await super()._bh_disconnect()
>>>> | File
>>>> "/home/niteesh/development/qemu/python/qemu/aqmp/protocol.py", line 644, in
>>>> _bh_disconnect
>>>> | await wait_closed(self._writer)
>>>> | File "/home/niteesh/development/qemu/python/qemu/aqmp/util.py",
>>>> line 137, in wait_closed
>>>> | await flush(writer)
>>>> | File "/home/niteesh/development/qemu/python/qemu/aqmp/util.py",
>>>> line 49, in flush
>>>> | await writer.drain()
>>>> | File "/usr/lib/python3.6/asyncio/streams.py", line 339, in drain
>>>> | yield from self._protocol._drain_helper()
>>>> | File "/usr/lib/python3.6/asyncio/streams.py", line 210, in
>>>> _drain_helper
>>>> | raise ConnectionResetError('Connection lost')
>>>> | ConnectionResetError: Connection lost
>>>>
>>>> --------------------------------------------------------------------------------------------------------------------------------------------
>>>>
>>>>
>>> I can't reproduce in Python 3.9, but I *can* reproduce in python 3.6
>>> using the pipenv environment; i.e.
>>>
>>> > make check-pipenv
>>> > pipenv shell
>>> > python3 -m qemu.aqmp.aqmp_tui 127.0.0.1:1234
>>>
>>> What python version are you using to see this failure? Is it 3.6 ?
>>>
>> Yes, I was using python 3.6. I just tried it on 3.8 and I don't face this
>> issue.
>>
>>>
>>> It seems like the wait_closed() wrapper I wrote isn't quite compatible
>>> with Python 3.6, it looks like it's not really safe to try and flush a
>>> closing socket. I was doing so in an attempt to tell when the socket had
>>> finished closing out its buffer (expecting it to normally be a no-op) but
>>> in this case even a no-op drain in 3.6 seems to raise an error if we
>>> attempt it after we've asked for the socket to close.
>>>
>>
>>
>>> wait_closed() was added in Python 3.7 and we just don't have access to
>>> it here ... I'm not sure if there's something else we can do here to serve
>>> as a workaround for not having this function.
>>>
>>> --js
>>>
>>>
> I can't find a *nice* workaround, but I found one that should probably
> work in most universes. We can remove this ugly code when we support 3.7 as
> a minimum. However, please try this patch as a fixup:
>
> diff --git a/python/qemu/aqmp/util.py b/python/qemu/aqmp/util.py
> index de0df44cbd7..eaa5fc7d5f9 100644
> --- a/python/qemu/aqmp/util.py
> +++ b/python/qemu/aqmp/util.py
> @@ -134,7 +134,17 @@ async def wait_closed(writer: asyncio.StreamWriter)
> -> None:
>
> while not transport.is_closing():
> await asyncio.sleep(0)
> - await flush(writer)
> +
> + # This is an ugly workaround, but it's the best I can come up with.
> + sock = transport.get_extra_info('socket')
> +
> + if sock is None:
> + # Our transport doesn't have a socket? ...
> + # Nothing we can reasonably do.
> + return
> +
> + while sock.fileno() != -1:
> + await asyncio.sleep(0)
>
Thanks for the patch. I am now able to disconnect/quit without any
exceptions.
Thanks,
Niteesh.
>
>
>
[-- Attachment #2: Type: text/html, Size: 11530 bytes --]
prev parent reply other threads:[~2021-07-21 20:18 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-17 0:32 [PATCH v2 00/24] python: introduce Asynchronous QMP package John Snow
2021-07-17 0:32 ` [PATCH v2 01/24] python/aqmp: add asynchronous QMP (AQMP) subpackage John Snow
2021-07-17 0:32 ` [PATCH v2 02/24] python/aqmp: add error classes John Snow
2021-08-03 16:01 ` Eric Blake
2021-08-03 17:34 ` John Snow
2021-08-03 17:40 ` Eric Blake
2021-08-03 18:01 ` John Snow
2021-07-17 0:32 ` [PATCH v2 03/24] python/pylint: Add exception for TypeVar names ('T') John Snow
2021-07-17 0:32 ` [PATCH v2 04/24] python/aqmp: add asyncio compatibility wrappers John Snow
2021-07-17 0:32 ` [PATCH v2 05/24] python/aqmp: add generic async message-based protocol support John Snow
2021-07-17 0:32 ` [PATCH v2 06/24] python/aqmp: add runstate state machine to AsyncProtocol John Snow
2021-07-17 0:32 ` [PATCH v2 07/24] python/aqmp: Add logging utility helpers John Snow
2021-07-17 0:32 ` [PATCH v2 08/24] python/aqmp: add logging to AsyncProtocol John Snow
2021-07-17 0:32 ` [PATCH v2 09/24] python/aqmp: add AsyncProtocol.accept() method John Snow
2021-07-17 0:32 ` [PATCH v2 10/24] python/aqmp: add configurable read buffer limit John Snow
2021-07-17 0:32 ` [PATCH v2 11/24] python/aqmp: add _cb_inbound and _cb_inbound logging hooks John Snow
2021-07-20 18:51 ` Niteesh G. S.
2021-07-20 19:13 ` John Snow
2021-07-17 0:32 ` [PATCH v2 12/24] python/aqmp: add AsyncProtocol._readline() method John Snow
2021-07-17 0:32 ` [PATCH v2 13/24] python/aqmp: add QMP Message format John Snow
2021-07-17 0:32 ` [PATCH v2 14/24] python/aqmp: add well-known QMP object models John Snow
2021-07-17 0:32 ` [PATCH v2 15/24] python/aqmp: add QMP event support John Snow
2021-07-17 0:32 ` [PATCH v2 16/24] python/pylint: disable too-many-function-args John Snow
2021-07-17 0:32 ` [PATCH v2 17/24] python/aqmp: add QMP protocol support John Snow
2021-07-17 0:32 ` [PATCH v2 18/24] python/pylint: disable no-member check John Snow
2021-07-17 0:32 ` [PATCH v2 19/24] python/aqmp: Add message routing to QMP protocol John Snow
2021-07-17 0:32 ` [PATCH v2 20/24] python/aqmp: add execute() interfaces John Snow
2021-07-17 0:32 ` [PATCH v2 21/24] python/aqmp: add _raw() execution interface John Snow
2021-07-17 0:32 ` [PATCH v2 22/24] python/aqmp: add asyncio_run compatibility wrapper John Snow
2021-07-17 0:32 ` [PATCH v2 23/24] python/aqmp: add scary message John Snow
2021-07-17 0:32 ` [PATCH v2 24/24] python/aqmp: add AsyncProtocol unit tests John Snow
2021-07-20 20:34 ` Beraldo Leal
2021-08-02 17:24 ` John Snow
2021-07-21 17:03 ` [PATCH v2 00/24] python: introduce Asynchronous QMP package Niteesh G. S.
[not found] ` <CAFn=p-YciuuRySs1F82ZyP_QGed=fbRZmzH3v7VNtdV-xM-XaA@mail.gmail.com>
[not found] ` <CAN6ztm-LKWMZTURfE_q0bWpoXVKGMoqmm2jj4_CTb_kj-kEjYg@mail.gmail.com>
2021-07-21 19:55 ` John Snow
2021-07-21 20:02 ` Niteesh G. S. [this message]
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='CAN6ztm9tgh=MsrYDBBi9ZcUCWabL+NKf9WeqKJO2e9HB6oHedg@mail.gmail.com' \
--to=niteesh.gs@gmail.com \
--cc=armbru@redhat.com \
--cc=crosa@redhat.com \
--cc=eblake@redhat.com \
--cc=ehabkost@redhat.com \
--cc=jsnow@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=wainersm@redhat.com \
--cc=wrampazz@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).