qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH v1 04/25] error: Add support for multiple errors


From: Peter Crosthwaite
Subject: [Qemu-devel] [RFC PATCH v1 04/25] error: Add support for multiple errors
Date: Thu, 10 Sep 2015 22:33:14 -0700

Allow errors to stack. If an error is already set, don't assert,
instead, form a linked list. Recent errors are at the front of the
list, older ones at the back.

The assertion against the destination erro already being set is
removed.

copy/free are all to call their functionality recursively.

Propagation is implemented as concatenation of two error lists.

Signed-off-by: Peter Crosthwaite <address@hidden>
---

 qapi/common.json |  5 ++++-
 util/error.c     | 27 +++++++++++++++++++++------
 2 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/qapi/common.json b/qapi/common.json
index bad56bf..04175db 100644
--- a/qapi/common.json
+++ b/qapi/common.json
@@ -22,11 +22,14 @@
 # @KVMMissingCap: the requested operation can't be fulfilled because a
 #                 required KVM capability is missing
 #
+# @MultipleErrors: Multiple errors have occured
+#
 # Since: 1.2
 ##
 { 'enum': 'ErrorClass',
   'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted',
-            'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }
+            'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap',
+            'MultipleErrors' ] }
 
 ##
 # @VersionTriple
diff --git a/util/error.c b/util/error.c
index b93e5c8..890ce58 100644
--- a/util/error.c
+++ b/util/error.c
@@ -18,28 +18,25 @@ struct Error
 {
     char *msg;
     ErrorClass err_class;
+    struct Error *next;
 };
 
 Error *error_abort;
 
 static void do_error_set(Error **errp, ErrorClass err_class,
                          void (*mod)(Error *, void *), void *mod_opaque,
-                         const char *fmt, ...)
+                         const char *fmt, va_list ap)
 {
     Error *err;
-    va_list ap;
     int saved_errno = errno;
 
     if (errp == NULL) {
         return;
     }
-    assert(*errp == NULL);
 
     err = g_malloc0(sizeof(*err));
 
-    va_start(ap, fmt);
     err->msg = g_strdup_vprintf(fmt, ap);
-    va_end(ap);
     if (mod) {
         mod(err, mod_opaque);
     }
@@ -50,6 +47,7 @@ static void do_error_set(Error **errp, ErrorClass err_class,
         abort();
     }
 
+    err->next = *errp;
     *errp = err;
 
     errno = saved_errno;
@@ -120,15 +118,22 @@ Error *error_copy(const Error *err)
 {
     Error *err_new;
 
+    if (!err) {
+        return NULL;
+    }
     err_new = g_malloc0(sizeof(*err));
     err_new->msg = g_strdup(err->msg);
     err_new->err_class = err->err_class;
+    err_new->next = error_copy(err->next);
 
     return err_new;
 }
 
 ErrorClass error_get_class(const Error *err)
 {
+    if (err->next) {
+        return ERROR_CLASS_MULTIPLE_ERRORS;
+    }
     return err->err_class;
 }
 
@@ -145,6 +150,9 @@ void error_report_err(Error *err)
 
 void error_free(Error *err)
 {
+    if (err->next) {
+        error_free(err->next);
+    }
     if (err) {
         g_free(err->msg);
         g_free(err);
@@ -156,8 +164,15 @@ void error_propagate(Error **dst_errp, Error *local_err)
     if (local_err && dst_errp == &error_abort) {
         error_report_err(local_err);
         abort();
-    } else if (dst_errp && !*dst_errp) {
+    } else if (dst_errp) {
+        Error *i;
+        Error *old_dst_err = *dst_errp;
+
         *dst_errp = local_err;
+        for (i = local_err; i; i = i->next) {
+            dst_errp = &i->next;
+        }
+        *dst_errp = old_dst_err;
     } else if (local_err) {
         error_free(local_err);
     }
-- 
1.9.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]