diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-08-22 13:13:35 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-08-22 13:13:35 +0100 |
commit | 810923480863c43ecb22ae124156298385439339 (patch) | |
tree | 786989fcc3da6a00bcabd53b9289bffcc2c0f55b /chardev | |
parent | f3b8f18ebf344ab359e8f79f6ed777e740dae77c (diff) | |
parent | 78d01598aea85841f0e4f8baf62c42b76230a81c (diff) |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* Longstanding chardev race condition fix (Berto)
* Cleanups and tests from the Meson POC (Marc-André, myself)
* Coalesced range cleanup (Peter)
# gpg: Signature made Wed 21 Aug 2019 18:27:43 BST
# gpg: using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream:
char-socket: Lock tcp_chr_disconnect() and socket_reconnect_timeout()
main-loop: Fix GSource leak in qio_task_thread_worker()
memory: Fix up memory_region_{add|del}_coalescing
memory: Remove has_coalesced_range counter
memory: Split zones when do coalesced_io_del()
memory: Refactor memory_region_clear_coalescing
minikconf: don't print CONFIG_FOO=n lines
configure: remove AUTOCONF_HOST
tests: add module loading test
module: return success on module load
module: use g_hash_table_add()
configure: define CONFIG_TOOLS here
qemu-ga: clean up TOOLS variable
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'chardev')
-rw-r--r-- | chardev/char-socket.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/chardev/char-socket.c b/chardev/char-socket.c index 7ca5d97af3..03f03407b0 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -150,7 +150,7 @@ 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_disconnect_locked(Chardev *chr); /* Called with chr_write_lock held. */ static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len) @@ -174,7 +174,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_disconnect_locked(chr); return len; } /* else let the read handler finish it properly */ } @@ -469,8 +469,9 @@ static void update_disconnected_filename(SocketChardev *s) /* NB may be called even if tcp_chr_connect has not been * reached, due to TLS or telnet initialization failure, * so can *not* assume s->state == TCP_CHARDEV_STATE_CONNECTED + * This must be called with chr->chr_write_lock held. */ -static void tcp_chr_disconnect(Chardev *chr) +static void tcp_chr_disconnect_locked(Chardev *chr) { SocketChardev *s = SOCKET_CHARDEV(chr); bool emit_close = s->state == TCP_CHARDEV_STATE_CONNECTED; @@ -490,6 +491,13 @@ static void tcp_chr_disconnect(Chardev *chr) } } +static void tcp_chr_disconnect(Chardev *chr) +{ + qemu_mutex_lock(&chr->chr_write_lock); + tcp_chr_disconnect_locked(chr); + qemu_mutex_unlock(&chr->chr_write_lock); +} + static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque) { Chardev *chr = CHARDEV(opaque); @@ -1131,8 +1139,10 @@ static gboolean socket_reconnect_timeout(gpointer opaque) Chardev *chr = CHARDEV(opaque); SocketChardev *s = SOCKET_CHARDEV(opaque); + qemu_mutex_lock(&chr->chr_write_lock); g_source_unref(s->reconnect_timer); s->reconnect_timer = NULL; + qemu_mutex_unlock(&chr->chr_write_lock); if (chr->be_open) { return false; |