Paolo Bonzini <[email protected]> writes:

> Il ven 30 gen 2026, 14:00 Markus Armbruster <[email protected]> ha scritto:
>
>> > Another benefit is that QEMU can report the first parsing error
>> > immediately, without waiting for delimiters to be balanced.
>>
>> Sounds promising!  Let's see...
>>
>> Before the series:
>>
>>      $ socat "READLINE,prompt=QMP> " UNIX-CONNECT:$HOME/work/images/test-qmp
>>     {"QMP": {"version": {"qemu": {"micro": 50, "minor": 2, "major": 10}, 
>> "package": "v10.2.0-567-gfb6b66de43-dirty"}, "capabilities": ["oob"]}}
>>     QMP> [{"a"]
>>
>> Parse error not diagnosed right away, but ...
>>
>>     QMP> }
>>     {"error": {"class": "GenericError", "desc": "JSON parse error, missing : 
>> in object pair"}}
>>
>> .... only when the streamer decides the expression is complete.
>>
>> After the series:
>>
>>     QMP> [{"a"]
>>     {"error": {"class": "GenericError", "desc": "JSON parse error at line 1, 
>> column 6, expecting ':'"}}
>>
>> Cool!  However, if I do it again, things fall apart:
>>
>>     QMP> [{"a"
>>     QMP> }
>>     QMP> }
>>     QMP> }
>>     QMP> ]
>>     QMP> ]
>>     {"error": {"class": "GenericError", "desc": "JSON parse error at line 7, 
>> column 1, expecting value"}}
>>
>> Parse error recovery not quite right?
>
> Well, if you read the above very carefully :) the error is *reported*
> immediately, but recovery still waits for delimiters to be balanced.

Yes, but the recovery regressed a bit.

Having read the entire series now, I wonder whether it's related to
capping @brace_count and @bracket_count at zero [PATCH 3].

My example input [{"a"] puts the parser in error recovery state with
brace_count == 1, bracket_count == 0.  Your parser will silently throw
away further input until brace_count drops to zero.

The old parser additionally snaps out of this unresponsive state when
bracked_count goes negative.

> In testing, when I got an error I just typed a long enough variant on
> "]}]}]}" and that is enough to recover—just like in the old parser.

With the old parser, I can park my finger on ']' or '}' for a moment,
hit return, and be good.  With the new one, I have to park on both.

More seriously, the new parser seems to break a recovery technique
documented in docs/interop/qmp-spec.rst:

    Forcing the JSON parser into known-good state
    ---------------------------------------------

    Incomplete or invalid input can leave the server's JSON parser in a
    state where it can't parse additional commands.  To get it back into
    known-good state, the client should provoke a lexical error.

    The cleanest way to do that is sending an ASCII control character
    other than ``\t`` (horizontal tab), ``\r`` (carriage return), or
    ``\n`` (new line).

Works with old parser:

    QMP> [{"a"]
    QMP> ^L
    {"error": {"class": "GenericError", "desc": "JSON parse error, stray '\f'"}}
    QMP> {}
    {"error": {"class": "GenericError", "desc": "QMP input lacks member 
'execute'"}}

Note: the ^L is a formfeed character.

New parser:

    QMP> [{"a"]
    {"error": {"class": "GenericError", "desc": "JSON parse error at line 1, 
column 6, expecting ':'"}}
    QMP> ^L
    QMP> {}

Good: the parse error is reported immediately.

Bad: the formfeed no longer forces the parser into known-good state.
This needs fixing.

>                                                                     Still
> the difference in error reporting matters, because it gives feedback that
> is immediately useful, rather than possibly delayed forever.

Reporting parse errors immediately is such a lovely quality of life
improvement.  May I have that without regressing error recovery?

> The policy is easy to change, either in v2 or in subsequent work, because
> recovery is layered on top of json-parser and its code is nothing more than
> "if you believe it's a good time to recover, reset the parser".
>
> Paolo

>> > On top of the benefits intrinsic in the push architecture, it so happens
>> > that it's really easy to add a location to JSON parsing errors now, so
>> > do that as well.
>> >
>> > Paolo
>>
>>


Reply via email to