[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 25/47] chardev/char-socket: add POLLHUP handler
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 25/47] chardev/char-socket: add POLLHUP handler |
Date: |
Mon, 5 Feb 2018 20:28:39 +0100 |
From: Klim Kireev <address@hidden>
The following behavior was observed for QEMU configured by libvirt
to use guest agent as usual for the guests without virtio-serial
driver (Windows or the guest remaining in BIOS stage).
In QEMU on first connect to listen character device socket
the listen socket is removed from poll just after the accept().
virtio_serial_guest_ready() returns 0 and the descriptor
of the connected Unix socket is removed from poll and it will
not be present in poll() until the guest will initialize the driver
and change the state of the serial to "guest connected".
In libvirt connect() to guest agent is performed on restart and
is run under VM state lock. Connect() is blocking and can
wait forever.
In this case libvirt can not perform ANY operation on that VM.
The bug can be easily reproduced this way:
Terminal 1:
qemu-system-x86_64 -m 512 -device pci-serial,chardev=serial1 -chardev
socket,id=serial1,path=/tmp/console.sock,server,nowait
(virtio-serial and isa-serial also fit)
Terminal 2:
minicom -D unix\#/tmp/console.sock
(type something and press enter)
C-a x (to exit)
Do 3 times:
minicom -D unix\#/tmp/console.sock
C-a x
It needs 4 connections, because the first one is accepted by QEMU, then two are
queued by
the kernel, and the 4th blocks.
The problem is that QEMU doesn't add a read watcher after succesful read
until the guest device wants to acquire recieved data, so
I propose to install a separate pullhup watcher regardless of
whether the device waits for data or not.
Signed-off-by: Klim Kireev <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
chardev/char-socket.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 77cdf48..a340af6 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -42,6 +42,7 @@ typedef struct {
QIOChannel *ioc; /* Client I/O channel */
QIOChannelSocket *sioc; /* Client master channel */
QIONetListener *listener;
+ GSource *hup_source;
QCryptoTLSCreds *tls_creds;
int connected;
int max_size;
@@ -352,6 +353,12 @@ static void tcp_chr_free_connection(Chardev *chr)
s->read_msgfds_num = 0;
}
+ if (s->hup_source != NULL) {
+ g_source_destroy(s->hup_source);
+ g_source_unref(s->hup_source);
+ s->hup_source = NULL;
+ }
+
tcp_set_msgfds(chr, NULL, 0);
remove_fd_in_watch(chr);
object_unref(OBJECT(s->sioc));
@@ -455,6 +462,15 @@ static gboolean tcp_chr_read(QIOChannel *chan,
GIOCondition cond, void *opaque)
return TRUE;
}
+static gboolean tcp_chr_hup(QIOChannel *channel,
+ GIOCondition cond,
+ void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ tcp_chr_disconnect(chr);
+ return G_SOURCE_REMOVE;
+}
+
static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
@@ -528,6 +544,12 @@ static void tcp_chr_connect(void *opaque)
tcp_chr_read,
chr, chr->gcontext);
}
+
+ s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
+ g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
+ chr, NULL);
+ g_source_attach(s->hup_source, chr->gcontext);
+
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
--
1.8.3.1
- [Qemu-devel] [PULL 14/47] Add missing hvdos public domain attribution:, (continued)
- [Qemu-devel] [PULL 14/47] Add missing hvdos public domain attribution:, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 15/47] hvf: ept_emulation_fault() needs NetApp BSD attribution, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 18/47] exynos4210: workaround UBSAN compilation error, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 16/47] Drop remaining bits of ia64 host support, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 19/47] build-sys: add --enable-sanitizers, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 21/47] vhost: add traces for memory listeners, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 20/47] ucontext: annotate coroutine stack for ASAN, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 17/47] sockets: fix parsing of ipv4/ipv6 opts in parse_socket_addr, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 23/47] vfio: listener unregister before unset container, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 22/47] arm: postpone device listener unregister, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 25/47] chardev/char-socket: add POLLHUP handler,
Paolo Bonzini <=
- [Qemu-devel] [PULL 24/47] memory: do explicit cleanup when remove listeners, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 28/47] ivshmem: Improve MSI irqfd error handling, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 29/47] ivshmem: Disable irqfd on device reset, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 27/47] ivshmem: Always remove irqfd notifiers, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 32/47] cpus: dummy: unregister thread with RCU, exit loop on unplug, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 30/47] cpus: hax: register/unregister thread with RCU, exit loop on unplug, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 31/47] cpus: kvm: unregister thread with RCU, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 26/47] ivshmem: Don't update non-existent MSI routes, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 35/47] cpus: join thread when removing a vCPU, Paolo Bonzini, 2018/02/05
- [Qemu-devel] [PULL 34/47] cpus: hvf: unregister thread with RCU, Paolo Bonzini, 2018/02/05