aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-11-19 11:29:00 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-11-19 11:29:01 +0000
commit6e5d4999c761ffa082f60d72a14e5c953515b417 (patch)
tree40c4a5780b7eb7e15fa380c68c90717abb83e5a1
parent385e43e6638464009e09cfaec254012e531f6342 (diff)
parent2895aaa139b3f916b3650ca516b35dceb9c0d4c4 (diff)
downloadqemu-6e5d4999c761ffa082f60d72a14e5c953515b417.tar.gz
Merge remote-tracking branch 'remotes/armbru/tags/pull-monitor-2019-11-19' into staging
Monitor patches for 2019-11-19 # gpg: Signature made Tue 19 Nov 2019 08:50:57 GMT # gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653 # gpg: issuer "armbru@redhat.com" # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full] # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full] # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-monitor-2019-11-19: monitor/qmp: resume monitor when clearing its queue Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--monitor/qmp.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/monitor/qmp.c b/monitor/qmp.c
index 9d9e5d8b274..b67a8e7d1f6 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -75,10 +75,35 @@ static void monitor_qmp_cleanup_req_queue_locked(MonitorQMP *mon)
}
}
-static void monitor_qmp_cleanup_queues(MonitorQMP *mon)
+static void monitor_qmp_cleanup_queue_and_resume(MonitorQMP *mon)
{
qemu_mutex_lock(&mon->qmp_queue_lock);
+
+ /*
+ * Same condition as in monitor_qmp_bh_dispatcher(), but before
+ * removing an element from the queue (hence no `- 1`).
+ * Also, the queue should not be empty either, otherwise the
+ * monitor hasn't been suspended yet (or was already resumed).
+ */
+ bool need_resume = (!qmp_oob_enabled(mon) ||
+ mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX)
+ && !g_queue_is_empty(mon->qmp_requests);
+
monitor_qmp_cleanup_req_queue_locked(mon);
+
+ if (need_resume) {
+ /*
+ * handle_qmp_command() suspended the monitor because the
+ * request queue filled up, to be resumed when the queue has
+ * space again. We just emptied it; resume the monitor.
+ *
+ * Without this, the monitor would remain suspended forever
+ * when we get here while the monitor is suspended. An
+ * unfortunately timed CHR_EVENT_CLOSED can do the trick.
+ */
+ monitor_resume(&mon->common);
+ }
+
qemu_mutex_unlock(&mon->qmp_queue_lock);
}
@@ -263,9 +288,10 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
/*
* Suspend the monitor when we can't queue more requests after
- * this one. Dequeuing in monitor_qmp_bh_dispatcher() will resume
- * it. Note that when OOB is disabled, we queue at most one
- * command, for backward compatibility.
+ * this one. Dequeuing in monitor_qmp_bh_dispatcher() or
+ * monitor_qmp_cleanup_queue_and_resume() will resume it.
+ * Note that when OOB is disabled, we queue at most one command,
+ * for backward compatibility.
*/
if (!qmp_oob_enabled(mon) ||
mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1) {
@@ -332,7 +358,7 @@ static void monitor_qmp_event(void *opaque, int event)
* stdio, it's possible that stdout is still open when stdin
* is closed.
*/
- monitor_qmp_cleanup_queues(mon);
+ monitor_qmp_cleanup_queue_and_resume(mon);
json_message_parser_destroy(&mon->parser);
json_message_parser_init(&mon->parser, handle_qmp_command,
mon, NULL);