From: Stratos Psomadakis <psomas@grnet.gr>
To: qemu-devel@nongnu.org
Cc: Synnefo Development <synnefo-devel@googlegroups.com>,
Stratos Psomadakis <psomas@grnet.gr>,
Ganeti Development <ganeti-devel@googlegroups.com>,
Dimitris Aragiorgis <dimara@grnet.gr>
Subject: [Qemu-devel] Possible bug in monitor code
Date: Wed, 22 Jan 2014 17:53:52 +0200 [thread overview]
Message-ID: <52DFE990.9000403@grnet.gr> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 3055 bytes --]
Hi,
we've encountered a weird issue regarding monitor (qmp and hmp) behavior
with qemu-1.7 (and qemu-1.5). The following steps will reproduce the issue:
1) Client A connects to qmp socket with socat
2) Client A gets greeting message {"QMP": {"version": ..}
3) Client A waits (select on the socket's fd)
4) Client B tries to connect to the *same* qmp socket with socat
5) Client B does *NOT* get any greating message
6) Client B waits (select on the socket's fd)
7) Client B closes connection (kill socat)
8) Client A quits too
9) Client C connects to qmp socket
10) Client C gets *two* greeting messages!!!
After some investigation, we traced it down to the monitor_flush()
function in monitor.c. Specifically, when a second client connects to
the qmp (client B), while another one is already using it (client A), we
get the following from stracing the second client (client B):
connect(3, {sa_family=AF_FILE, path="foo.mon"}, 9) = 0
getsockname(3, {sa_family=AF_FILE, NULL}, [2]) = 0
select(4, [0 3], [1 3], [], NULL) = 2 (out [1 3])
select(4, [0 3], [], [], NULL
So, the connect() syscall from client B succeeds, although client B
connection has not yet been accepted by the qmp server (it's still in
the backlog of the qmp listening socket).
After killing client B and then client A, we see the following when
stracing the qemu proc:
22363 accept4(6, {sa_family=AF_FILE, NULL}, [2], SOCK_CLOEXEC) = 9
22363 fcntl(9, F_GETFL) = 0x2 (flags O_RDWR)
22363 fcntl(9, F_SETFL, O_RDWR|O_NONBLOCK) = 0
22363 fstat(9, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
22363 fcntl(9, F_GETFL) = 0x802 (flags
O_RDWR|O_NONBLOCK)
22363 write(9, "{\"QMP\": {\"version\": {\"qemu\": {\"m"..., 127) =
-1 EPIPE (Broken pipe)
22363 --- SIGPIPE (Broken pipe) @ 0 (0) ---
The qmp server / qemu accepts the connection from client B (who has now
closed the connection) and tries to write the greeting message to the
socket fd. This results in write returning an error (EPIPE).
The monitor_flush() function doesn't seem to handle this case (write
error). Instead, it adds a watch / handler to retry the write operation.
Thus, mon->outbuf is not cleaned up properly, which results in duplicate
greeting messages for the next client to connect.
The following seems to do the trick.
diff --git a/monitor.c b/monitor.c
index 845f608..5622f20 100644
--- a/monitor.c
+++ b/monitor.c
@@ -288,8 +288,8 @@ void monitor_flush(Monitor *mon)
if (len && !mon->mux_out) {
rc = qemu_chr_fe_write(mon->chr, (const uint8_t *) buf, len);
- if (rc == len) {
- /* all flushed */
+ if ((rc < 0 && errno != EAGAIN) || (rc == len)) {
+ /* all flushed or error */
QDECREF(mon->outbuf);
mon->outbuf = qstring_new();
return;
Comments?
Thanks,
Stratos
--
Stratos Psomadakis
<psomas@grnet.gr>
[-- Attachment #1.2: Type: text/html, Size: 4264 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
next reply other threads:[~2014-01-22 16:16 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-22 15:53 Stratos Psomadakis [this message]
2014-01-23 3:07 ` [Qemu-devel] Possible bug in monitor code Fam Zheng
2014-01-23 10:17 ` Stratos Psomadakis
2014-01-24 23:48 ` Luiz Capitulino
2014-01-27 10:30 ` [Qemu-devel] [PATCH] monitor: Cleanup mon->outbuf on write error Stratos Psomadakis
2014-01-29 10:46 ` Stratos Psomadakis
2014-01-29 14:12 ` Luiz Capitulino
-- strict thread matches above, loose matches on Subject: below --
2014-01-23 11:23 [Qemu-devel] Possible bug in monitor code Fam Zheng
2014-01-23 13:44 ` Luiz Capitulino
2014-01-23 13:54 ` Luiz Capitulino
2014-01-23 15:33 ` Stratos Psomadakis
2014-01-23 18:28 ` Luiz Capitulino
2014-01-24 10:14 ` Stratos Psomadakis
2014-01-24 10:52 ` Apollon Oikonomopoulos
2014-01-24 14:14 ` Luiz Capitulino
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=52DFE990.9000403@grnet.gr \
--to=psomas@grnet.gr \
--cc=dimara@grnet.gr \
--cc=ganeti-devel@googlegroups.com \
--cc=qemu-devel@nongnu.org \
--cc=synnefo-devel@googlegroups.com \
/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.