The current output of the qapi code generator includes some chained error handling, which looks like:
| visit_start_struct(v, (void **)obj, "foo", name, sizeof(FOO), &err); | if (!err) { | if (*obj) { | visit_type_FOO_fields(v, obj, errp); | } | visit_end_struct(v, &err); | } | error_propagate(errp, err); Although there are plans to revisit that code for qemu 2.6, it is still a useful idiom to mention. It is safe because error_propagate() is different than most functions in that you can pass in an already-set errp, and it still does the right thing. Also, describe an alternative form of chained error handling that was proposed during the qapi work, and which may be a bit more obvious to a reader what is happening: | visit_start_implicit_struct(v, (void **)obj, sizeof(FOO), &err); | if (!err) { | visit_type_FOO_fields(v, obj, &err); | visit_end_implicit_struct(v, err ? NULL : &err); | } | error_propagate(errp, err); Signed-off-by: Eric Blake <ebl...@redhat.com> --- based on feedback of my qapi series v5 7/46; doc only, so might be worth having in 2.5 --- include/qapi/error.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/qapi/error.h b/include/qapi/error.h index 4d42cdc..4310195 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -76,6 +76,21 @@ * But when all you do with the error is pass it on, please use * foo(arg, errp); * for readability. + * + * In a situation where cleanup must happen even if a first step fails, + * but the cleanup may also set an error, the first error to occur will + * take priority when combined by: + * Error *err = NULL; + * action1(arg, errp); + * action2(arg, &err); + * error_propagate(errp, err); + * or by: + * Error *err = NULL; + * action1(arg, &err); + * action2(arg, err ? NULL : &err); + * error_propagate(errp, err); + * although the second form is required if any further error handling + * will inspect err to see if all earlier locations succeeded. */ #ifndef ERROR_H -- 2.4.3