All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrangé" <berrange@redhat.com>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: "QEMU Developers" <qemu-devel@nongnu.org>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Philippe Mathieu-Daudé" <philmd@linaro.org>
Subject: Re: socket chardevs: data loss when other end closes connection?
Date: Tue, 18 Oct 2022 20:21:48 +0100	[thread overview]
Message-ID: <Y078zCODLU5XsJYs@redhat.com> (raw)
In-Reply-To: <CAFEAcA9t7ujfVVOdg4m0PBt1DkYY+UpDr2tA_doEb71+r-gfXA@mail.gmail.com>

On Tue, Oct 18, 2022 at 06:55:08PM +0100, Peter Maydell wrote:
> I've been looking at a (long-standing) bug where an avocado test
> intermittently fails.
> 
> This happens because at the avocado end we write "halt\r" to the
> serial console, which is wired up to a Unix socket; but at the UART
> model we only ever see the 'h' character and no further data.  As far
> as I can tell this happens because Avocado closes the socket and the
> QEMU socket chardev layer loses the last few characters of data that
> the guest hasn't yet read at that point.
> 
> This is what seems to me to be going on:
>  * Avocado writes the data ('halt\r') and closes the socket
>    pretty much immediately afterwards
>  * At the glib layer, the socket is polled, and it gets G_IO_IN
>    and G_IO_HUP, indicating "readable, and also closed"
>  * glib's source dispatch mechanism first calls tcp_chr_read()
>    to handle the G_IO_IN part
>  * tcp_chr_read() reads a single byte (the 'h'), because
>    SocketChardev::max_size is 1 (which in turn is because the
>    device model's can_write function returned 1 to say that's
>    all it can accept for now). So there's still data to be
>    read in future
>  * glib now calls tcp_chr_hup() because of the G_IO_HUP (as part
>    of the same handle-all-the-sources loop)
>  * tcp_chr_hup() calls tcp_chr_disconnect(), which basically
>    frees everything, tells the chardev backend that the connection
>    just closed, etc
>  * the data remaining in the socket to be read after the 'h'
>    is never read
> 
> How is this intended to work? I guess the socket ought to go
> into some kind of "disconnecting" state, but not actually do
> a tcp_chr_disconnect() until all the data has been read via
> tcp_chr_read() and it's finally got an EOF indication back from
> tcp_chr_recv() ?

Right, this is basically broken by (lack of) design right now.

The main problem here is that we're watching the socket twice.
One set of callbacks added with io_add_watch_poll, and then
a second callback added with qio_chanel_create_watch just for
G_IO_HUP.

We need there to be only 1 callback, and when that callback
gets  G_IO_IN, it should *ignore* G_IO_HUP until tcp_chr_recv
returns 0 to indicate EOF. This would cause tcp_chr_read to
be invoked repeatedly with G_IO_IN | G_IO_HUP, as we read
"halt\r" one byte at a time.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



  reply	other threads:[~2022-10-18 19:28 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-18 17:55 socket chardevs: data loss when other end closes connection? Peter Maydell
2022-10-18 19:21 ` Daniel P. Berrangé [this message]
2022-10-19 16:26   ` Peter Maydell
2022-10-19 16:29     ` Daniel P. Berrangé

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=Y078zCODLU5XsJYs@redhat.com \
    --to=berrange@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=philmd@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.