From patchwork Fri Apr 24 19:01:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Capitulino X-Patchwork-Id: 464375 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40D9C1402DB for ; Sat, 25 Apr 2015 05:03:48 +1000 (AEST) Received: from localhost ([::1]:46040 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ylit8-0002ko-EG for incoming@patchwork.ozlabs.org; Fri, 24 Apr 2015 15:03:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56991) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yliqu-0006Kq-HZ for qemu-devel@nongnu.org; Fri, 24 Apr 2015 15:01:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Yliqt-00026k-F6 for qemu-devel@nongnu.org; Fri, 24 Apr 2015 15:01:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60205) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yliqt-00026g-8V for qemu-devel@nongnu.org; Fri, 24 Apr 2015 15:01:27 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t3OJ1PnK013382 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 24 Apr 2015 15:01:25 -0400 Received: from localhost (ovpn-113-99.phx2.redhat.com [10.3.113.99]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t3OJ1Oc7032553; Fri, 24 Apr 2015 15:01:24 -0400 From: Luiz Capitulino To: peter.maydell@linaro.org Date: Fri, 24 Apr 2015 15:01:18 -0400 Message-Id: <1429902078-21770-5-git-send-email-lcapitulino@redhat.com> In-Reply-To: <1429902078-21770-1-git-send-email-lcapitulino@redhat.com> References: <1429902078-21770-1-git-send-email-lcapitulino@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PULL 4/4] qmp: Give saner messages related to qmp_capabilities misuse X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Eric Blake Pretending that QMP doesn't understand a command merely because we are not in the right mode doesn't help first-time users figure out what to do to correct things. Although the documentation for QMP calls out capabilities negotiation, we should also make it clear in our error messages what we were expecting. With this patch, I now get the following transcript: $ ./x86_64-softmmu/qemu-system-x86_64 -qmp stdio -nodefaults {"QMP": {"version": {"qemu": {"micro": 93, "minor": 2, "major": 2}, "package": ""}, "capabilities": []}} {"execute":"huh"} {"error": {"class": "CommandNotFound", "desc": "The command huh has not been found"}} {"execute":"quit"} {"error": {"class": "CommandNotFound", "desc": "Expecting capabilities negotiation with 'qmp_capabilities' before command 'quit'"}} {"execute":"qmp_capabilities"} {"return": {}} {"execute":"qmp_capabilities"} {"error": {"class": "CommandNotFound", "desc": "Capabilities negotiation is already complete, command 'qmp_capabilities' ignored"}} {"execute":"quit"} {"return": {}} {"timestamp": {"seconds": 1429110729, "microseconds": 181935}, "event": "SHUTDOWN"} Signed-off-by: Eric Blake Tested-By: Kashyap Chamarthy Reviewed-by: Paulo Vital Reviewed-by: John Snow Signed-off-by: Luiz Capitulino --- monitor.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/monitor.c b/monitor.c index 68873ec..9f37700 100644 --- a/monitor.c +++ b/monitor.c @@ -4783,10 +4783,22 @@ static int monitor_can_read(void *opaque) return (mon->suspend_cnt == 0) ? 1 : 0; } -static int invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd) +static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd) { - int is_cap = cmd->mhandler.cmd_new == do_qmp_capabilities; - return (qmp_cmd_mode(mon) ? is_cap : !is_cap); + bool is_cap = cmd->mhandler.cmd_new == do_qmp_capabilities; + if (is_cap && qmp_cmd_mode(mon)) { + qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND, + "Capabilities negotiation is already complete, command " + "'%s' ignored", cmd->name); + return true; + } + if (!is_cap && !qmp_cmd_mode(mon)) { + qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND, + "Expecting capabilities negotiation with " + "'qmp_capabilities' before command '%s'", cmd->name); + return true; + } + return false; } /* @@ -5080,11 +5092,14 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) cmd_name = qdict_get_str(input, "execute"); trace_handle_qmp_command(mon, cmd_name); cmd = qmp_find_cmd(cmd_name); - if (!cmd || invalid_qmp_mode(mon, cmd)) { + if (!cmd) { qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found", cmd_name); goto err_out; } + if (invalid_qmp_mode(mon, cmd)) { + goto err_out; + } obj = qdict_get(input, "arguments"); if (!obj) {