qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: QMP and the 'id' parameter


From: John Snow
Subject: Re: QMP and the 'id' parameter
Date: Tue, 10 Nov 2020 11:32:57 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.3.1

On 11/10/20 1:22 AM, Markus Armbruster wrote:
John Snow <jsnow@redhat.com> writes:

The QMP specification states:

NOTE: Some errors can occur before the Server is able to read the "id"
member, in these cases the "id" member will not be part of the error
response, even if provided by the client.

I am assuming this case ONLY occurs for Parse errors:

{'class': 'GenericError', 'desc': 'JSON parse error, expecting value'}

There are more "desc" possible, actually.

The JSON parser gets fed chunks of input, and calls a callback for every
full JSON value, and on parse error.

QMP's callback is handle_qmp_command().  Parameter @req is the parsed
JSON value, parameter @err is the (parse) error object, and exactly one
of them is non-null.

1. Parse error

If @err, we send an error response for it.  It never has "id".  See
qmp_error_response() caller monitor_qmp_dispatcher_co().  The possible
@err are:

     $ grep error_setg qobject/json-*[ch]
     qobject/json-parser.c:    error_setg(&ctxt->err, "JSON parse error, %s", 
message);

This is a syntax error.

Search for parse_error() to see the possible @message patterns.

     qobject/json-streamer.c:        error_setg(&err, "JSON parse error, stray 
'%s'", input->str);

This is a lexical error.

     qobject/json-streamer.c:        error_setg(&err, "JSON token size limit 
exceeded");
     qobject/json-streamer.c:        error_setg(&err, "JSON token count limit 
exceeded");
     qobject/json-streamer.c:        error_setg(&err, "JSON nesting depth limit 
exceeded");

These are (intentional) parser limits.

2. Successful parse

If @req, it's a successful parse.

If @req is not a JSON object, there is no "id".  qmp_dispatch() reports

         error_setg(&err, "QMP input must be a JSON object");

If @req is a JSON object, it has "id" exactly when the client supplied
one.  The response mirrors @req's "id".  See qmp_error_response() caller
qmp_dispatch().


That's very helpful, thank you. So in summary, the possibilities are:

1. syntax error (with several descriptions)
2. lexical error (with several descriptions, templated from one message)
3. lexical limitation (with several descriptions)
4. grammatical error ("QMP input must be a JSON object")

(I know we have declared the error_class passe and we now prefer "generic_error", but I lack the history lesson on why we do that. Wouldn't the error_class here be helpful for interpreting the response? It helps differentiate between 'The RPC call was received' vs 'The RPC call was received, but failed.' which may have semantic differences for who wants to consume the error: the QMP library itself, or the user making the RPC call. No?)

And I am assuming, in the context of a client that /always/ sets an
'id' for its execute statements, that this means that any error
response we receive without an 'id' field *must* be associated with
the most-recently-sent command.

Only if the client keeps no more than one command in flight.


OK, so without engaging the OOB capability, we receive responses strictly in a FIFO manner, always.

So if we have:

Send exec A, Send exec B, Send exec C

and then we receive an error response with no ID attached, we know it must be "A" that errored. Correct?

Command responses get sent strictly in order (even parse errors), except
for commands executed out-of-band.

If the client sends N JSON values, and only then reads responses, and
there are no parse errors, then it'll get N responses.  The i-th
response is for the i-th JSON value, except responses to OOB command may
"jump the queue".


Let's assume now that A, B, and C are *all* OOB commands:

- Send exec-oob A
- Send exec-oob B
- Send exec-oob C

My client now reads an error message that has no ID attached. Which command execution was this associated with?

Is it necessarily "A" if we have not yet received any other response?

With parse errors, it can get a different number of responses.


Oh, uhm -- if the parse error was bad enough that it didn't even notice we sent it three commands, right? ... So if we see a parse error, we might not know which, if any, of our queued commands were seen or can still expect a response.

That seems difficult to code around, unless I misunderstand.

(Every parser error I receive -- which I can "guess" that it's a parser error by the lack of an 'id' field, potentially invalidates the entire queue?)

Questions?


A few :)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]