From 3777d36e674ca3b75b63413b4fb506b108309144 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 24 Apr 2020 10:43:24 +0200 Subject: qapi: Belatedly update visitor.h's big comment for QAPI modules Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <20200424084338.26803-2-armbru@redhat.com> --- include/qapi/visitor.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include/qapi/visitor.h') diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index c5b23851a1..f8a0fc1ea9 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -58,7 +58,7 @@ * * where T is FOO for scalar types, and FOO * otherwise. The scalar * visitors are declared here; the remaining visitors are generated in - * qapi-visit.h. + * qapi-visit-MODULE.h. * * The @name parameter of visit_type_FOO() describes the relation * between this QAPI value and its parent container. When visiting @@ -86,16 +86,16 @@ * by manual construction. * * For the QAPI object types (structs, unions, and alternates), there - * is an additional generated function in qapi-visit.h compatible - * with: + * is an additional generated function in qapi-visit-MODULE.h + * compatible with: * * void visit_type_FOO_members(Visitor *v, FOO *obj, Error **errp); * * for visiting the members of a type without also allocating the QAPI * struct. * - * Additionally, in qapi-types.h, all QAPI pointer types (structs, - * unions, alternates, and lists) have a generated function compatible + * Additionally, QAPI pointer types (structs, unions, alternates, and + * lists) have a generated function in qapi-types-MODULE.h compatible * with: * * void qapi_free_FOO(FOO *obj); -- cgit 1.4.1 From 294c90662ac9daae2c3bbf608296cf037925bd95 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 24 Apr 2020 10:43:25 +0200 Subject: qapi: Fix the virtual walk example in visitor.h's big comment Call visit_check_list(). Missed in commit a4a1c70dc7 "qapi: Make input visitors detect unvisited list tails". Drop an irrelevant error_propagate() while there. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <20200424084338.26803-3-armbru@redhat.com> --- include/qapi/visitor.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/qapi/visitor.h') diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index f8a0fc1ea9..7f63e4c381 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -215,6 +215,9 @@ * goto outlist; * } * outlist: + * if (!err) { + * visit_check_list(v, &err); + * } * visit_end_list(v, NULL); * if (!err) { * visit_check_struct(v, &err); @@ -222,7 +225,6 @@ * outobj: * visit_end_struct(v, NULL); * out: - * error_propagate(errp, err); * visit_free(v); * */ -- cgit 1.4.1 From 782586c77103d297f38e78950dfbe2a31a3b2924 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 24 Apr 2020 10:43:26 +0200 Subject: qapi: Fix typo in visit_start_list()'s contract Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <20200424084338.26803-4-armbru@redhat.com> --- include/qapi/visitor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/qapi/visitor.h') diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 7f63e4c381..c5d0ce9184 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -345,9 +345,9 @@ void visit_end_struct(Visitor *v, void **obj); * input visitors set *@list to NULL. * * After visit_start_list() succeeds, the caller may visit its members - * one after the other. A real visit (where @obj is non-NULL) uses + * one after the other. A real visit (where @list is non-NULL) uses * visit_next_list() for traversing the linked list, while a virtual - * visit (where @obj is NULL) uses other means. For each list + * visit (where @list is NULL) uses other means. For each list * element, call the appropriate visit_type_FOO() with name set to * NULL and obj set to the address of the value member of the list * element. Finally, visit_end_list() needs to be called with the -- cgit 1.4.1 From c5460d5e19b4c531e86f8be0e00ab463fae7548b Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 24 Apr 2020 10:43:27 +0200 Subject: qapi: Document @errp usage more thoroughly in visitor.h Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <20200424084338.26803-5-armbru@redhat.com> --- include/qapi/visitor.h | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'include/qapi/visitor.h') diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index c5d0ce9184..09df7099c6 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -284,9 +284,7 @@ void visit_free(Visitor *v); * into *@obj. @obj may also be NULL for a virtual walk, in which * case @size is ignored. * - * @errp obeys typical error usage, and reports failures such as a - * member @name is not present, or present but not an object. On - * error, input visitors set *@obj to NULL. + * On failure, set *@obj to NULL and store an error through @errp. * * After visit_start_struct() succeeds, the caller may visit its * members one after the other, passing the member's name and address @@ -303,8 +301,7 @@ void visit_start_struct(Visitor *v, const char *name, void **obj, /* * Prepare for completing an object visit. * - * @errp obeys typical error usage, and reports failures such as - * unparsed keys remaining in the input stream. + * On failure, store an error through @errp. * * Should be called prior to visit_end_struct() if all other * intermediate visit steps were successful, to allow the visitor one @@ -340,9 +337,7 @@ void visit_end_struct(Visitor *v, void **obj); * allow @list to be NULL for a virtual walk, in which case @size is * ignored. * - * @errp obeys typical error usage, and reports failures such as a - * member @name is not present, or present but not a list. On error, - * input visitors set *@list to NULL. + * On failure, set *@list to NULL and store an error through @errp. * * After visit_start_list() succeeds, the caller may visit its members * one after the other. A real visit (where @list is non-NULL) uses @@ -376,8 +371,7 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size); /* * Prepare for completing a list visit. * - * @errp obeys typical error usage, and reports failures such as - * unvisited list tail remaining in the input stream. + * On failure, store an error through @errp. * * Should be called prior to visit_end_list() if all other * intermediate visit steps were successful, to allow the visitor one @@ -409,8 +403,10 @@ void visit_end_list(Visitor *v, void **list); * * @obj must not be NULL. Input and clone visitors use @size to * determine how much memory to allocate into *@obj, then determine - * the qtype of the next thing to be visited, stored in (*@obj)->type. - * Other visitors will leave @obj unchanged. + * the qtype of the next thing to be visited, and store it in + * (*@obj)->type. Other visitors leave @obj unchanged. + * + * On failure, set *@obj to NULL and store an error through @errp. * * If successful, this must be paired with visit_end_alternate() with * the same @obj to clean up, even if visiting the contents of the @@ -463,8 +459,9 @@ bool visit_optional(Visitor *v, const char *name, bool *present); * * Currently, all input visitors parse text input, and all output * visitors produce text output. The mapping between enumeration - * values and strings is done by the visitor core, using @strings; it - * should be the ENUM_lookup array from visit-types.h. + * values and strings is done by the visitor core, using @lookup. + * + * On failure, store an error through @errp. * * May call visit_type_str() under the hood, and the enum visit may * fail even if the corresponding string visit succeeded; this implies @@ -488,6 +485,8 @@ bool visit_is_input(Visitor *v); * * @obj must be non-NULL. Input visitors set *@obj to the value; * other visitors will leave *@obj unchanged. + * + * On failure, store an error through @errp. */ void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp); @@ -564,6 +563,8 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj, * * @obj must be non-NULL. Input visitors set *@obj to the value; * other visitors will leave *@obj unchanged. + * + * On failure, store an error through @errp. */ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); @@ -581,6 +582,8 @@ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); * It is safe to cast away const when preparing a (const char *) value * into @obj for use by an output visitor. * + * On failure, set *@obj to NULL and store an error through @errp. + * * FIXME: Callers that try to output NULL *obj should not be allowed. */ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); @@ -594,6 +597,8 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); * @obj must be non-NULL. Input visitors set *@obj to the value; * other visitors will leave *@obj unchanged. Visitors should * document if infinity or NaN are not permitted. + * + * On failure, store an error through @errp. */ void visit_type_number(Visitor *v, const char *name, double *obj, Error **errp); @@ -608,6 +613,8 @@ void visit_type_number(Visitor *v, const char *name, double *obj, * other visitors will leave *@obj unchanged. *@obj must be non-NULL * for output visitors. * + * On failure, set *@obj to NULL and store an error through @errp. + * * Note that some kinds of input can't express arbitrary QObject. * E.g. the visitor returned by qobject_input_visitor_new_keyval() * can't create numbers or booleans, only strings. @@ -622,6 +629,8 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp); * * @obj must be non-NULL. Input visitors set *@obj to the value; * other visitors ignore *@obj. + * + * On failure, set *@obj to NULL and store an error through @errp. */ void visit_type_null(Visitor *v, const char *name, QNull **obj, Error **errp); -- cgit 1.4.1 From 554d6586ae96216771fe701c9d3a321e2adb057b Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 24 Apr 2020 10:43:28 +0200 Subject: qapi: Polish prose in visitor.h Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <20200424084338.26803-6-armbru@redhat.com> --- include/qapi/visitor.h | 104 +++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 50 deletions(-) (limited to 'include/qapi/visitor.h') diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 09df7099c6..a425ea514c 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -25,19 +25,21 @@ * for doing work at each node of a QAPI graph; it can also be used * for a virtual walk, where there is no actual QAPI C struct. * - * There are four kinds of visitor classes: input visitors (QObject, - * string, and QemuOpts) parse an external representation and build - * the corresponding QAPI graph, output visitors (QObject and string) take - * a completed QAPI graph and generate an external representation, the - * dealloc visitor can take a QAPI graph (possibly partially - * constructed) and recursively free its resources, and the clone - * visitor performs a deep clone of one QAPI object to another. While - * the dealloc and QObject input/output visitors are general, the string, - * QemuOpts, and clone visitors have some implementation limitations; - * see the documentation for each visitor for more details on what it - * supports. Also, see visitor-impl.h for the callback contracts - * implemented by each visitor, and docs/devel/qapi-code-gen.txt for more - * about the QAPI code generator. + * There are four kinds of visitors: input visitors (QObject, string, + * and QemuOpts) parse an external representation and build the + * corresponding QAPI object, output visitors (QObject and string) + * take a QAPI object and generate an external representation, the + * dealloc visitor takes a QAPI object (possibly partially + * constructed) and recursively frees it, and the clone visitor + * performs a deep clone of a QAPI object. + * + * While the dealloc and QObject input/output visitors are general, + * the string, QemuOpts, and clone visitors have some implementation + * limitations; see the documentation for each visitor for more + * details on what it supports. Also, see visitor-impl.h for the + * callback contracts implemented by each visitor, and + * docs/devel/qapi-code-gen.txt for more about the QAPI code + * generator. * * All of the visitors are created via: * @@ -45,11 +47,15 @@ * * A visitor should be used for exactly one top-level visit_type_FOO() * or virtual walk; if that is successful, the caller can optionally - * call visit_complete() (for now, useful only for output visits, but - * safe to call on all visits). Then, regardless of success or - * failure, the user should call visit_free() to clean up resources. - * It is okay to free the visitor without completing the visit, if - * some other error is detected in the meantime. + * call visit_complete() (useful only for output visits, but safe to + * call on all visits). Then, regardless of success or failure, the + * user should call visit_free() to clean up resources. It is okay to + * free the visitor without completing the visit, if some other error + * is detected in the meantime. + * + * The clone and dealloc visitor should not be used directly outside + * of QAPI code. Use the qapi_free_FOO() and QAPI_CLONE() instead, + * described below. * * All QAPI types have a corresponding function with a signature * roughly compatible with this: @@ -68,22 +74,26 @@ * alternate, @name should equal the name used for visiting the * alternate. * - * The visit_type_FOO() functions expect a non-null @obj argument; - * they allocate *@obj during input visits, leave it unchanged on - * output visits, and recursively free any resources during a dealloc - * visit. Each function also takes the customary @errp argument (see + * The visit_type_FOO() functions take a non-null @obj argument; they + * allocate *@obj during input visits, leave it unchanged during + * output and clone visits, and free it (recursively) during a dealloc + * visit. + * + * Each function also takes the customary @errp argument (see * qapi/error.h for details), for reporting any errors (such as if a * member @name is not present, or is present but not the specified * type). * * If an error is detected during visit_type_FOO() with an input - * visitor, then *@obj will be NULL for pointer types, and left - * unchanged for scalar types. Using an output or clone visitor with - * an incomplete object has undefined behavior (other than a special - * case for visit_type_str() treating NULL like ""), while the dealloc - * visitor safely handles incomplete objects. Since input visitors - * never produce an incomplete object, such an object is possible only - * by manual construction. + * visitor, then *@obj will be set to NULL for pointer types, and left + * unchanged for scalar types. + * + * Using an output or clone visitor with an incomplete object has + * undefined behavior (other than a special case for visit_type_str() + * treating NULL like ""), while the dealloc visitor safely handles + * incomplete objects. Since input visitors never produce an + * incomplete object, such an object is possible only by manual + * construction. * * For the QAPI object types (structs, unions, and alternates), there * is an additional generated function in qapi-visit-MODULE.h @@ -100,23 +110,20 @@ * * void qapi_free_FOO(FOO *obj); * - * where behaves like free() in that @obj may be NULL. Such objects - * may also be used with the following macro, provided alongside the - * clone visitor: + * Does nothing when @obj is NULL. + * + * Such objects may also be used with macro * * Type *QAPI_CLONE(Type, src); * - * in order to perform a deep clone of @src. Because of the generated - * qapi_free functions and the QAPI_CLONE() macro, the clone and - * dealloc visitor should not be used directly outside of QAPI code. + * in order to perform a deep clone of @src. * - * QAPI types can also inherit from a base class; when this happens, a - * function is generated for easily going from the derived type to the - * base type: + * For QAPI types can that inherit from a base type, a function is + * generated for going from the derived type to the base type: * * BASE *qapi_CHILD_base(CHILD *obj); * - * For a real QAPI struct, typical input usage involves: + * Typical input visitor usage involves: * * * Foo *f; @@ -153,7 +160,7 @@ * qapi_free_FooList(l); * * - * Similarly, typical output usage is: + * Typical output visitor usage: * * * Foo *f = ...obtain populated object... @@ -172,17 +179,8 @@ * visit_free(v); * * - * When visiting a real QAPI struct, this file provides several - * helpers that rely on in-tree information to control the walk: - * visit_optional() for the 'has_member' field associated with - * optional 'member' in the C struct; and visit_next_list() for - * advancing through a FooList linked list. Similarly, the - * visit_is_input() helper makes it possible to write code that is - * visitor-agnostic everywhere except for cleanup. Only the generated - * visit_type functions need to use these helpers. - * * It is also possible to use the visitors to do a virtual walk, where - * no actual QAPI struct is present. In this situation, decisions + * no actual QAPI object is present. In this situation, decisions * about what needs to be walked are made by the calling code, and * structured visits are split between pairs of start and end methods * (where the end method must be called if the start function @@ -227,6 +225,12 @@ * out: * visit_free(v); * + * + * This file provides helpers for use by the generated + * visit_type_FOO(): visit_optional() for the 'has_member' field + * associated with optional 'member' in the C struct, + * visit_next_list() for advancing through a FooList linked list, and + * visit_is_input() for cleaning up on failure. */ /*** Useful types ***/ -- cgit 1.4.1 From 8e08bf4ea24c3e6e07fab2c1b5bdcc7b104012c4 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 24 Apr 2020 10:43:29 +0200 Subject: qapi: Assert incomplete object occurs only in dealloc visitor Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <20200424084338.26803-7-armbru@redhat.com> --- docs/devel/qapi-code-gen.txt | 2 ++ include/qapi/visitor.h | 5 +++++ qapi/qapi-visit-core.c | 5 +++++ scripts/qapi/visit.py | 4 ++++ 4 files changed, 16 insertions(+) (limited to 'include/qapi/visitor.h') diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 1967adfa92..c6dd1891c3 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -1446,6 +1446,8 @@ Example: goto out; } if (!*obj) { + /* incomplete */ + assert(visit_is_dealloc(v)); goto out_obj; } visit_type_UserDefOne_members(v, *obj, &err); diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index a425ea514c..2d40d2fe0f 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -479,6 +479,11 @@ void visit_type_enum(Visitor *v, const char *name, int *obj, */ bool visit_is_input(Visitor *v); +/* + * Check if visitor is a dealloc visitor. + */ +bool visit_is_dealloc(Visitor *v); + /*** Visiting built-in types ***/ /* diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 5365561b07..d4aac206cf 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -142,6 +142,11 @@ bool visit_is_input(Visitor *v) return v->type == VISITOR_INPUT; } +bool visit_is_dealloc(Visitor *v) +{ + return v->type == VISITOR_DEALLOC; +} + void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) { assert(obj); diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py index 23d9194aa4..e3467b770b 100644 --- a/scripts/qapi/visit.py +++ b/scripts/qapi/visit.py @@ -189,6 +189,8 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error goto out; } if (!*obj) { + /* incomplete */ + assert(visit_is_dealloc(v)); goto out_obj; } switch ((*obj)->type) { @@ -260,6 +262,8 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error goto out; } if (!*obj) { + /* incomplete */ + assert(visit_is_dealloc(v)); goto out_obj; } visit_type_%(c_name)s_members(v, *obj, &err); -- cgit 1.4.1 From 1f5842487ad5b3d59ea32742e30dc7441f413e6c Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 24 Apr 2020 10:43:35 +0200 Subject: qapi: Only input visitors can actually fail The previous few commits have made this more obvious, and removed the one exception. Time to clarify the documentation, and drop dead error checking. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <20200424084338.26803-13-armbru@redhat.com> --- block.c | 9 +-------- block/sheepdog.c | 9 +-------- blockdev.c | 16 ++-------------- hw/core/machine-hmp-cmds.c | 2 +- include/qapi/visitor-impl.h | 4 ++++ include/qapi/visitor.h | 40 ++++++++++++++++++++++++---------------- monitor/hmp-cmds.c | 3 ++- 7 files changed, 35 insertions(+), 48 deletions(-) (limited to 'include/qapi/visitor.h') diff --git a/block.c b/block.c index 2e3905c99e..c11385ae05 100644 --- a/block.c +++ b/block.c @@ -2982,7 +2982,6 @@ BdrvChild *bdrv_open_child(const char *filename, BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) { BlockDriverState *bs = NULL; - Error *local_err = NULL; QObject *obj = NULL; QDict *qdict = NULL; const char *reference = NULL; @@ -2995,11 +2994,7 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) assert(ref->type == QTYPE_QDICT); v = qobject_output_visitor_new(&obj); - visit_type_BlockdevOptions(v, NULL, &options, &local_err); - if (local_err) { - error_propagate(errp, local_err); - goto fail; - } + visit_type_BlockdevOptions(v, NULL, &options, &error_abort); visit_complete(v, &obj); qdict = qobject_to(QDict, obj); @@ -3017,8 +3012,6 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp); obj = NULL; - -fail: qobject_unref(obj); visit_free(v); return bs; diff --git a/block/sheepdog.c b/block/sheepdog.c index 59f7ebb171..5f3aead038 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1854,19 +1854,12 @@ static int sd_create_prealloc(BlockdevOptionsSheepdog *location, int64_t size, Visitor *v; QObject *obj = NULL; QDict *qdict; - Error *local_err = NULL; int ret; v = qobject_output_visitor_new(&obj); - visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &local_err); + visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &error_abort); visit_free(v); - if (local_err) { - error_propagate(errp, local_err); - qobject_unref(obj); - return -EINVAL; - } - qdict = qobject_to(QDict, obj); qdict_flatten(qdict); diff --git a/blockdev.c b/blockdev.c index 5faddaa705..9da960b1e7 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3725,14 +3725,8 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) QObject *obj; Visitor *v = qobject_output_visitor_new(&obj); QDict *qdict; - Error *local_err = NULL; - - visit_type_BlockdevOptions(v, NULL, &options, &local_err); - if (local_err) { - error_propagate(errp, local_err); - goto fail; - } + visit_type_BlockdevOptions(v, NULL, &options, &error_abort); visit_complete(v, &obj); qdict = qobject_to(QDict, obj); @@ -3760,7 +3754,6 @@ void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp) AioContext *ctx; QObject *obj; Visitor *v = qobject_output_visitor_new(&obj); - Error *local_err = NULL; BlockReopenQueue *queue; QDict *qdict; @@ -3777,12 +3770,7 @@ void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp) } /* Put all options in a QDict and flatten it */ - visit_type_BlockdevOptions(v, NULL, &options, &local_err); - if (local_err) { - error_propagate(errp, local_err); - goto fail; - } - + visit_type_BlockdevOptions(v, NULL, &options, &error_abort); visit_complete(v, &obj); qdict = qobject_to(QDict, obj); diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c index b76f7223af..39999c47c5 100644 --- a/hw/core/machine-hmp-cmds.c +++ b/hw/core/machine-hmp-cmds.c @@ -113,7 +113,7 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict) while (m) { v = string_output_visitor_new(false, &str); - visit_type_uint16List(v, NULL, &m->value->host_nodes, NULL); + visit_type_uint16List(v, NULL, &m->value->host_nodes, &error_abort); monitor_printf(mon, "memory backend: %s\n", m->value->id); monitor_printf(mon, " size: %" PRId64 "\n", m->value->size); monitor_printf(mon, " merge: %s\n", diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 252206dc0d..98dc533d39 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -43,6 +43,10 @@ typedef enum VisitorType { struct Visitor { + /* + * Only input visitors may fail! + */ + /* Must be set to visit structs */ void (*start_struct)(Visitor *v, const char *name, void **obj, size_t size, Error **errp); diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 2d40d2fe0f..5573906966 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -82,7 +82,7 @@ * Each function also takes the customary @errp argument (see * qapi/error.h for details), for reporting any errors (such as if a * member @name is not present, or is present but not the specified - * type). + * type). Only input visitors can fail. * * If an error is detected during visit_type_FOO() with an input * visitor, then *@obj will be set to NULL for pointer types, and left @@ -164,19 +164,14 @@ * * * Foo *f = ...obtain populated object... - * Error *err = NULL; * Visitor *v; * Type *result; * * v = FOO_visitor_new(..., &result); - * visit_type_Foo(v, NULL, &f, &err); - * if (err) { - * ...handle error... - * } else { - * visit_complete(v, &result); - * ...use result... - * } + * visit_type_Foo(v, NULL, &f, &error_abort); + * visit_complete(v, &result); * visit_free(v); + * ...use result... * * * It is also possible to use the visitors to do a virtual walk, where @@ -289,6 +284,7 @@ void visit_free(Visitor *v); * case @size is ignored. * * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. * * After visit_start_struct() succeeds, the caller may visit its * members one after the other, passing the member's name and address @@ -305,7 +301,8 @@ void visit_start_struct(Visitor *v, const char *name, void **obj, /* * Prepare for completing an object visit. * - * On failure, store an error through @errp. + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. * * Should be called prior to visit_end_struct() if all other * intermediate visit steps were successful, to allow the visitor one @@ -342,6 +339,7 @@ void visit_end_struct(Visitor *v, void **obj); * ignored. * * On failure, set *@list to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. * * After visit_start_list() succeeds, the caller may visit its members * one after the other. A real visit (where @list is non-NULL) uses @@ -375,7 +373,8 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size); /* * Prepare for completing a list visit. * - * On failure, store an error through @errp. + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. * * Should be called prior to visit_end_list() if all other * intermediate visit steps were successful, to allow the visitor one @@ -411,6 +410,7 @@ void visit_end_list(Visitor *v, void **list); * (*@obj)->type. Other visitors leave @obj unchanged. * * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. * * If successful, this must be paired with visit_end_alternate() with * the same @obj to clean up, even if visiting the contents of the @@ -465,11 +465,13 @@ bool visit_optional(Visitor *v, const char *name, bool *present); * visitors produce text output. The mapping between enumeration * values and strings is done by the visitor core, using @lookup. * - * On failure, store an error through @errp. + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. * * May call visit_type_str() under the hood, and the enum visit may * fail even if the corresponding string visit succeeded; this implies - * that visit_type_str() must have no unwelcome side effects. + * that an input visitor's visit_type_str() must have no unwelcome + * side effects. */ void visit_type_enum(Visitor *v, const char *name, int *obj, const QEnumLookup *lookup, Error **errp); @@ -495,7 +497,8 @@ bool visit_is_dealloc(Visitor *v); * @obj must be non-NULL. Input visitors set *@obj to the value; * other visitors will leave *@obj unchanged. * - * On failure, store an error through @errp. + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. */ void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp); @@ -573,7 +576,8 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj, * @obj must be non-NULL. Input visitors set *@obj to the value; * other visitors will leave *@obj unchanged. * - * On failure, store an error through @errp. + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. */ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); @@ -592,6 +596,7 @@ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); * into @obj for use by an output visitor. * * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. * * FIXME: Callers that try to output NULL *obj should not be allowed. */ @@ -607,7 +612,8 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp); * other visitors will leave *@obj unchanged. Visitors should * document if infinity or NaN are not permitted. * - * On failure, store an error through @errp. + * On failure, store an error through @errp. Can happen only when @v + * is an input visitor. */ void visit_type_number(Visitor *v, const char *name, double *obj, Error **errp); @@ -623,6 +629,7 @@ void visit_type_number(Visitor *v, const char *name, double *obj, * for output visitors. * * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. * * Note that some kinds of input can't express arbitrary QObject. * E.g. the visitor returned by qobject_input_visitor_new_keyval() @@ -640,6 +647,7 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp); * other visitors ignore *@obj. * * On failure, set *@obj to NULL and store an error through @errp. + * Can happen only when @v is an input visitor. */ void visit_type_null(Visitor *v, const char *name, QNull **obj, Error **errp); diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 9b94e67879..7f6e982dc8 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -334,7 +334,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) Visitor *v; char *str; v = string_output_visitor_new(false, &str); - visit_type_uint32List(v, NULL, &info->postcopy_vcpu_blocktime, NULL); + visit_type_uint32List(v, NULL, &info->postcopy_vcpu_blocktime, + &error_abort); visit_complete(v, &str); monitor_printf(mon, "postcopy vcpu blocktime: %s\n", str); g_free(str); -- cgit 1.4.1