As per the QMP spec, asynchronous messages should not be sent during
negotiation.

The event sending code checks if the monitor is in the negotiation phase
by checking for mon->commands != qmp_cap_negotiation_commands. However,
events may be incorrectly sent from the point the connection is opened
to when monitor_qmp_event() sets the negotiation phase.

Ensure it is always in the negotiation phase when a connection is opened
by initializing it during monitor init and close.

Signed-off-by: Ross Lagerwall <[email protected]>
---
 monitor/qmp.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/monitor/qmp.c b/monitor/qmp.c
index e1419a9efa39..187a5d7477c9 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -462,15 +462,15 @@ static void monitor_qmp_event(void *opaque, QEMUChrEvent 
event)
 
     switch (event) {
     case CHR_EVENT_OPENED:
-        WITH_QEMU_LOCK_GUARD(&mon->common.mon_lock) {
-            mon->commands = &qmp_cap_negotiation_commands;
-            monitor_qmp_caps_reset(mon);
-        }
         data = qmp_greeting(mon);
         qmp_send_response(mon, data);
         qobject_unref(data);
         break;
     case CHR_EVENT_CLOSED:
+        WITH_QEMU_LOCK_GUARD(&mon->common.mon_lock) {
+            mon->commands = &qmp_cap_negotiation_commands;
+            monitor_qmp_caps_reset(mon);
+        }
         /*
          * Note: this is only useful when the output of the chardev
          * backend is still open.  For example, when the backend is
@@ -527,6 +527,7 @@ void monitor_init_qmp(Chardev *chr, bool pretty, Error 
**errp)
     monitor_data_init(&mon->common, true, false,
                       qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_GCONTEXT));
 
+    mon->commands = &qmp_cap_negotiation_commands;
     mon->pretty = pretty;
 
     qemu_mutex_init(&mon->qmp_queue_lock);
-- 
2.52.0


Reply via email to