From 4f141f42f2ae8cf509495ee0962fd45e160f33af Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Wed, 23 Jan 2019 16:48:07 +0100 Subject: [PATCH] Hack to fix race in tcp_chr_disconnect() --- chardev/char-socket.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/chardev/char-socket.c b/chardev/char-socket.c index eaa8e8b68f..9c326dcbf3 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -124,7 +124,12 @@ static void tcp_chr_accept(QIONetListener *listener, void *opaque); static int tcp_chr_read_poll(void *opaque); -static void tcp_chr_disconnect(Chardev *chr); +static void tcp_chr_do_disconnect(Chardev *chr, bool locked); + +static void tcp_chr_disconnect(Chardev *chr) +{ + tcp_chr_do_disconnect(chr, false); +} /* Called with chr_write_lock held. */ static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len) @@ -148,7 +153,7 @@ static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len) if (ret < 0 && errno != EAGAIN) { if (tcp_chr_read_poll(chr) <= 0) { - tcp_chr_disconnect(chr); + tcp_chr_do_disconnect(chr, true); return len; } /* else let the read handler finish it properly */ } @@ -444,8 +449,12 @@ static void update_disconnected_filename(SocketChardev *s) * reached, due to TLS or telnet initialization failure, * so can *not* assume s->connected == true */ -static void tcp_chr_disconnect(Chardev *chr) +static void tcp_chr_do_disconnect(Chardev *chr, bool locked) { + if (!locked) { + qemu_mutex_lock(&chr->chr_write_lock); + } + SocketChardev *s = SOCKET_CHARDEV(chr); bool emit_close = s->connected; @@ -462,6 +471,10 @@ static void tcp_chr_disconnect(Chardev *chr) if (s->reconnect_time) { qemu_chr_socket_restart_timer(chr); } + + if (!locked) { + qemu_mutex_unlock(&chr->chr_write_lock); + } } static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque) -- 2.20.1