From: Marc-André Lureau <marcandre.lur...@redhat.com> Existing clients may not handle async replies very well. In order to avoid the potential issues, let's introduce a capability that the client must declare in order to make use of async commands.
Eventually, client should already handle unexpected events after a command is sent, instead of the reply. It shouldn't be much more complicated to handle unmatched returns from previous async commands. Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com> --- monitor.c | 28 ++++++++++++++++++++++++++-- qapi-schema.json | 16 ++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/monitor.c b/monitor.c index ca3db31..fda1ddd 100644 --- a/monitor.c +++ b/monitor.c @@ -524,8 +524,31 @@ static void monitor_qapi_event_init(void) qmp_event_set_func_emit(monitor_qapi_event_queue); } -void qmp_qmp_capabilities(Error **errp) +static void disable_async(QmpCommand *cmd, void *opaque) { + if (cmd->type == QCT_ASYNC) { + cmd->enabled = FALSE; + } +} + +void qmp_qmp_capabilities(bool has_capabilities, + QMPCapabilityList *capabilities, Error **errp) +{ + bool has_async = false; + + if (has_capabilities) { + while (capabilities) { + if (capabilities->value == QMP_CAPABILITY_ASYNC) { + has_async = true; + } + capabilities = capabilities->next; + } + } + + if (!has_async) { + qmp_for_each_command(disable_async, NULL); + } + cur_mon->qmp.in_command_mode = true; } @@ -3694,7 +3717,8 @@ static QObject *get_qmp_greeting(void) assert(cmd && cmd->fn); cmd->fn(NULL, &ver, NULL); - return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': []}}",ver); + return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': [" + "'async']}}", ver); } static void monitor_qmp_event(void *opaque, int event) diff --git a/qapi-schema.json b/qapi-schema.json index b01de49..99c986d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -70,11 +70,23 @@ # = QMP commands ## +# @QMPCapability +# +# QMP protocol capabilities +# +# @async: enables async messages +# +# Since: 2.5 +## +{ 'enum': 'QMPCapability', + 'data': ['async'] } + +## # @qmp_capabilities: # # Enable QMP capabilities. # -# Arguments: None. +# @capabilities: #optional an array of QMPCapability # # Example: # @@ -84,7 +96,7 @@ # Notes: This command must be issued before issuing any other command. # ## -{ 'command': 'qmp_capabilities' } +{ 'command': 'qmp_capabilities', 'data': { '*capabilities': ['QMPCapability'] } } ## # @LostTickPolicy: -- 2.4.3