diff mbox series

[RFC,v5,080/126] QAPI: introduce ERRP_AUTO_PROPAGATE

Message ID 20191011160552.22907-81-vsementsov@virtuozzo.com
State New
Headers show
Series error: auto propagated local_err | expand

Commit Message

Vladimir Sementsov-Ogievskiy Oct. 11, 2019, 4:05 p.m. UTC
If we want to add some info to errp (by error_prepend() or
error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro.
Otherwise, this info will not be added when errp == &fatal_err
(the program will exit prior to the error_append_hint() or
error_prepend() call).  Fix such cases.

If we want to check error after errp-function call, we need to
introduce local_err and than propagate it to errp. Instead, use
ERRP_AUTO_PROPAGATE macro, benefits are:
1. No need of explicit error_propagate call
2. No need of explicit local_err variable: use errp directly
3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or
   &error_fatel, this means that we don't break error_abort
   (we'll abort on error_set, not on error_propagate)

This commit (together with its neighbors) was generated by

for f in $(git grep -l errp \*.[ch]); do \
    spatch --sp-file scripts/coccinelle/auto-propagated-errp.cocci \
    --macro-file scripts/cocci-macro-file.h --in-place --no-show-diff $f; \
done;

then fix a bit of compilation problems: coccinelle for some reason
leaves several
f() {
    ...
    goto out;
    ...
    out:
}
patterns, with "out:" at function end.

then
./python/commit-per-subsystem.py MAINTAINERS "$(< auto-msg)"

(auto-msg was a file with this commit message)

Still, for backporting it may be more comfortable to use only the first
command and then do one huge commit.

Reported-by: Kevin Wolf <kwolf@redhat.com>
Reported-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
 qapi/qapi-visit-core.c      | 56 ++++++++++++++++---------------------
 qapi/qmp-dispatch.c         |  7 ++---
 qapi/string-input-visitor.c |  7 ++---
 3 files changed, 30 insertions(+), 40 deletions(-)

Comments

Eric Blake Oct. 11, 2019, 7:22 p.m. UTC | #1
On 10/11/19 11:05 AM, Vladimir Sementsov-Ogievskiy wrote:
> If we want to add some info to errp (by error_prepend() or
> error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro.
> Otherwise, this info will not be added when errp == &fatal_err
> (the program will exit prior to the error_append_hint() or
> error_prepend() call).  Fix such cases.
> 
> If we want to check error after errp-function call, we need to
> introduce local_err and than propagate it to errp. Instead, use
> ERRP_AUTO_PROPAGATE macro, benefits are:
> 1. No need of explicit error_propagate call
> 2. No need of explicit local_err variable: use errp directly
> 3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or
>     &error_fatel, this means that we don't break error_abort
>     (we'll abort on error_set, not on error_propagate)
> 

> Reported-by: Kevin Wolf <kwolf@redhat.com>
> Reported-by: Greg Kurz <groug@kaod.org>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> ---
>   qapi/qapi-visit-core.c      | 56 ++++++++++++++++---------------------
>   qapi/qmp-dispatch.c         |  7 ++---
>   qapi/string-input-visitor.c |  7 ++---
>   3 files changed, 30 insertions(+), 40 deletions(-)
> 

> +++ b/qapi/qmp-dispatch.c
> @@ -78,7 +78,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob,
>   static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
>                                   bool allow_oob, Error **errp)
>   {
> -    Error *local_err = NULL;
> +    ERRP_AUTO_PROPAGATE();
>       bool oob;
>       const char *command;
>       QDict *args, *dict;
> @@ -129,9 +129,8 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
>           qobject_ref(args);
>       }
>   
> -    cmd->fn(args, &ret, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> +    cmd->fn(args, &ret, errp);
> +    if (*errp) {
>       } else if (cmd->options & QCO_NO_SUCCESS_RESP) {

Looks a bit funny with the empty if clause, but not worth changing.

>           g_assert(!ret);
>       } else if (!ret) {

Reviewed-by: Eric Blake <eblake@redhat.com>
diff mbox series

Patch

diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 5365561b07..f8c5be9130 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -39,18 +39,17 @@  void visit_free(Visitor *v)
 void visit_start_struct(Visitor *v, const char *name, void **obj,
                         size_t size, Error **errp)
 {
-    Error *err = NULL;
+    ERRP_AUTO_PROPAGATE();
 
     trace_visit_start_struct(v, name, obj, size);
     if (obj) {
         assert(size);
         assert(!(v->type & VISITOR_OUTPUT) || *obj);
     }
-    v->start_struct(v, name, obj, size, &err);
+    v->start_struct(v, name, obj, size, errp);
     if (obj && (v->type & VISITOR_INPUT)) {
-        assert(!err != !*obj);
+        assert(!*errp != !*obj);
     }
-    error_propagate(errp, err);
 }
 
 void visit_check_struct(Visitor *v, Error **errp)
@@ -70,15 +69,14 @@  void visit_end_struct(Visitor *v, void **obj)
 void visit_start_list(Visitor *v, const char *name, GenericList **list,
                       size_t size, Error **errp)
 {
-    Error *err = NULL;
+    ERRP_AUTO_PROPAGATE();
 
     assert(!list || size >= sizeof(GenericList));
     trace_visit_start_list(v, name, list, size);
-    v->start_list(v, name, list, size, &err);
+    v->start_list(v, name, list, size, errp);
     if (list && (v->type & VISITOR_INPUT)) {
-        assert(!(err && *list));
+        assert(!(*errp && *list));
     }
-    error_propagate(errp, err);
 }
 
 GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
@@ -106,18 +104,17 @@  void visit_start_alternate(Visitor *v, const char *name,
                            GenericAlternate **obj, size_t size,
                            Error **errp)
 {
-    Error *err = NULL;
+    ERRP_AUTO_PROPAGATE();
 
     assert(obj && size >= sizeof(GenericAlternate));
     assert(!(v->type & VISITOR_OUTPUT) || *obj);
     trace_visit_start_alternate(v, name, obj, size);
     if (v->start_alternate) {
-        v->start_alternate(v, name, obj, size, &err);
+        v->start_alternate(v, name, obj, size, errp);
     }
     if (v->type & VISITOR_INPUT) {
-        assert(v->start_alternate && !err != !*obj);
+        assert(v->start_alternate && !*errp != !*obj);
     }
-    error_propagate(errp, err);
 }
 
 void visit_end_alternate(Visitor *v, void **obj)
@@ -152,12 +149,11 @@  void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
 static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
                              uint64_t max, const char *type, Error **errp)
 {
-    Error *err = NULL;
+    ERRP_AUTO_PROPAGATE();
     uint64_t value = *obj;
 
-    v->type_uint64(v, name, &value, &err);
-    if (err) {
-        error_propagate(errp, err);
+    v->type_uint64(v, name, &value, errp);
+    if (*errp) {
     } else if (value > max) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                    name ? name : "null", type);
@@ -211,12 +207,11 @@  static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
                             int64_t min, int64_t max, const char *type,
                             Error **errp)
 {
-    Error *err = NULL;
+    ERRP_AUTO_PROPAGATE();
     int64_t value = *obj;
 
-    v->type_int64(v, name, &value, &err);
-    if (err) {
-        error_propagate(errp, err);
+    v->type_int64(v, name, &value, errp);
+    if (*errp) {
     } else if (value < min || value > max) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                    name ? name : "null", type);
@@ -286,7 +281,7 @@  void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
 
 void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
 {
-    Error *err = NULL;
+    ERRP_AUTO_PROPAGATE();
 
     assert(obj);
     /* TODO: Fix callers to not pass NULL when they mean "", so that we
@@ -294,11 +289,10 @@  void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
     assert(!(v->type & VISITOR_OUTPUT) || *obj);
      */
     trace_visit_type_str(v, name, obj);
-    v->type_str(v, name, obj, &err);
+    v->type_str(v, name, obj, errp);
     if (v->type & VISITOR_INPUT) {
-        assert(!err != !*obj);
+        assert(!*errp != !*obj);
     }
-    error_propagate(errp, err);
 }
 
 void visit_type_number(Visitor *v, const char *name, double *obj,
@@ -311,16 +305,15 @@  void visit_type_number(Visitor *v, const char *name, double *obj,
 
 void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
 {
-    Error *err = NULL;
+    ERRP_AUTO_PROPAGATE();
 
     assert(obj);
     assert(v->type != VISITOR_OUTPUT || *obj);
     trace_visit_type_any(v, name, obj);
-    v->type_any(v, name, obj, &err);
+    v->type_any(v, name, obj, errp);
     if (v->type == VISITOR_INPUT) {
-        assert(!err != !*obj);
+        assert(!*errp != !*obj);
     }
-    error_propagate(errp, err);
 }
 
 void visit_type_null(Visitor *v, const char *name, QNull **obj,
@@ -352,13 +345,12 @@  static void output_type_enum(Visitor *v, const char *name, int *obj,
 static void input_type_enum(Visitor *v, const char *name, int *obj,
                             const QEnumLookup *lookup, Error **errp)
 {
-    Error *local_err = NULL;
+    ERRP_AUTO_PROPAGATE();
     int64_t value;
     char *enum_str;
 
-    visit_type_str(v, name, &enum_str, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    visit_type_str(v, name, &enum_str, errp);
+    if (*errp) {
         return;
     }
 
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index bc264b3c9b..205e183871 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -78,7 +78,7 @@  static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob,
 static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
                                 bool allow_oob, Error **errp)
 {
-    Error *local_err = NULL;
+    ERRP_AUTO_PROPAGATE();
     bool oob;
     const char *command;
     QDict *args, *dict;
@@ -129,9 +129,8 @@  static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
         qobject_ref(args);
     }
 
-    cmd->fn(args, &ret, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    cmd->fn(args, &ret, errp);
+    if (*errp) {
     } else if (cmd->options & QCO_NO_SUCCESS_RESP) {
         g_assert(!ret);
     } else if (!ret) {
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index 9be418b6d6..ef9b9b961a 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -313,14 +313,13 @@  static void parse_type_uint64(Visitor *v, const char *name, uint64_t *obj,
 static void parse_type_size(Visitor *v, const char *name, uint64_t *obj,
                             Error **errp)
 {
+    ERRP_AUTO_PROPAGATE();
     StringInputVisitor *siv = to_siv(v);
-    Error *err = NULL;
     uint64_t val;
 
     assert(siv->lm == LM_NONE);
-    parse_option_size(name, siv->string, &val, &err);
-    if (err) {
-        error_propagate(errp, err);
+    parse_option_size(name, siv->string, &val, errp);
+    if (*errp) {
         return;
     }