On Tue, Jul 28, 2026 at 05:29:35PM -0400, Peter Xu wrote:
> On Tue, Jul 28, 2026 at 05:04:16PM -0400, Peter Xu wrote:
> > In an unlikely case, when a migration stream is attached to the destination
> > QEMU and only send <4 bytes to the channel as magic, it's possible that
> > migration_channel_read_peek() may spin forever.
> >
> > Fix it by adding a manual sleep for partial read.
> >
> > Since the path isn't attached to a coroutine, it means when partial read
> > happens, there's yet not much we can do but hang the main thread, it will
> > happen even for len==0 case. It means monitors can hang due to this,
> > either partial read or no data arrived (but connection established).
> >
> > Leave this for later, the hope is this is extremely rare in production.
> >
> > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3889
> > Reported-by: Feifan Qian <[email protected]>
> > Cc: Daniel P. Berrangé <[email protected]>
> > Signed-off-by: Peter Xu <[email protected]>
> > ---
> > migration/channel.c | 11 +++++++++--
> > 1 file changed, 9 insertions(+), 2 deletions(-)
> >
> > diff --git a/migration/channel.c b/migration/channel.c
> > index 1e2935f926..f446561b59 100644
> > --- a/migration/channel.c
> > +++ b/migration/channel.c
> > @@ -296,9 +296,16 @@ int migration_channel_read_peek(QIOChannel *ioc,
> >
> > if (len == buflen) {
> > break;
> > + } else if (len == 0) {
>
> I think this should be QIO_CHANNEL_ERR_BLOCK, not 0.. I'll fix it when I
> post v3, and I'll do some more tests.
I just found that I cannot really hit this path.. because essentially
migration_channel_read_peek() is too early, and we haven't set iochannel to
be in non-blocking (QEMU only does it for the main channel; for the rest
channels they're always in blocking mode).
But still, instead of asserting it, I plan to keep this line so this code
is generic to blocking mode too in the future.
>
> > + qio_channel_wait_cond(ioc, G_IO_IN);
> > + } else {
> > + /*
> > + * When partially ready, we can't use qio_channel_wait_cond()
> > + * because it will return immediately. Apply a manual wait.
> > + */
> > + assert(!qemu_in_coroutine());
> > + g_usleep(1000);
> > }
> > -
> > - qio_channel_wait_cond(ioc, G_IO_IN);
> > }
> >
> > return 0;
> > --
> > 2.54.0
> >
>
> --
> Peter Xu
--
Peter Xu