@@ -3899,16 +3899,9 @@ static int monitor_can_read(void *opaque)
return !atomic_mb_read(&mon->suspend_cnt);
}
-/* take the ownership of rsp & id */
-static void monitor_qmp_respond(Monitor *mon, QDict *rsp, QObject *id)
+/* take the ownership of rsp */
+static void monitor_qmp_respond(Monitor *mon, QDict *rsp)
{
- if (!rsp) {
- return;
- }
-
- if (id) {
- qdict_put_obj(rsp, "id", id);
- }
if (mon->qmp.commands == &qmp_cap_negotiation_commands) {
QDict *qdict = qdict_get_qdict(rsp, "error");
if (qdict
@@ -3941,11 +3934,9 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj)
{
Monitor *mon, *old_mon;
QDict *req, *rsp = NULL;
- QObject *id;
req = req_obj->req;
mon = req_obj->mon;
- id = req_obj->id;
g_free(req_obj);
@@ -3963,7 +3954,9 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj)
cur_mon = old_mon;
/* Respond if necessary */
- monitor_qmp_respond(mon, rsp, id);
+ if (rsp) {
+ monitor_qmp_respond(mon, rsp);
+ }
QDECREF(req);
@@ -4060,9 +4053,6 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
goto err;
}
- qobject_incref(id);
- qdict_del(qdict, "id");
-
req_obj = g_new0(QMPRequest, 1);
req_obj->mon = mon;
req_obj->id = id;
@@ -4094,7 +4084,6 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
qapi_event_send_command_dropped(id,
COMMAND_DROP_REASON_QUEUE_FULL,
&error_abort);
- qobject_decref(id);
qobject_decref(req);
g_free(req_obj);
return;
@@ -4117,7 +4106,7 @@ err:
qdict = qdict_new();
qdict_put_obj(qdict, "error", qmp_build_error_object(err));
error_free(err);
- monitor_qmp_respond(mon, qdict, id);
+ monitor_qmp_respond(mon, qdict);
qobject_decref(req);
}
@@ -151,10 +151,15 @@ QDict *qmp_dispatch(QmpCommandList *cmds, QDict *req)
Error *err = NULL;
QObject *ret;
QDict *rsp;
+ QObject *id = qdict_get(req, "id");
ret = do_qmp_dispatch(cmds, req, &err);
rsp = qdict_new();
+ if (id) {
+ qobject_incref(id);
+ qdict_put_obj(rsp, "id", id);
+ }
if (err) {
qdict_put_obj(rsp, "error", qmp_build_error_object(err));
error_free(err);
@@ -277,6 +277,22 @@ static void test_dealloc_partial(void)
qapi_free_UserDefTwo(ud2);
}
+static void test_dispatch_cmd_id(void)
+{
+ QDict *resp, *req = qdict_new();
+
+ qdict_put_str(req, "execute", "user_def_cmd");
+ qdict_put_str(req, "id", "ID42");
+
+ resp = qmp_dispatch(&qmp_commands, req);
+ assert(resp != NULL);
+ assert(!qdict_haskey(resp, "error"));
+ assert(!strcmp(qdict_get_str(resp, "id"), "ID42"));
+
+ QDECREF(resp);
+ QDECREF(req);
+}
+
int main(int argc, char **argv)
{
@@ -287,6 +303,7 @@ int main(int argc, char **argv)
g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io);
g_test_add_func("/qmp/dispatch_cmd_success_response",
test_dispatch_cmd_success_response);
+ g_test_add_func("/qmp/dispatch_cmd_id", test_dispatch_cmd_id);
g_test_add_func("/qmp/dealloc_types", test_dealloc_types);
g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial);
This is convenient for other QMP users such as QGA and tests and simplifies a bit the qemu monitor code, and avoids modifying the request. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- monitor.c | 23 ++++++----------------- qapi/qmp-dispatch.c | 5 +++++ tests/test-qmp-cmds.c | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 17 deletions(-)