|
@@ -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);
|
|
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);
|
|
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);
|
|
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
|
|
* 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) ||
|
|
if (!qmp_oob_enabled(mon) ||
|
|
mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1) {
|
|
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
|
|
* stdio, it's possible that stdout is still open when stdin
|
|
* is closed.
|
|
* is closed.
|
|
*/
|
|
*/
|
|
- monitor_qmp_cleanup_queues(mon);
|
|
|
|
|
|
+ monitor_qmp_cleanup_queue_and_resume(mon);
|
|
json_message_parser_destroy(&mon->parser);
|
|
json_message_parser_destroy(&mon->parser);
|
|
json_message_parser_init(&mon->parser, handle_qmp_command,
|
|
json_message_parser_init(&mon->parser, handle_qmp_command,
|
|
mon, NULL);
|
|
mon, NULL);
|