diff mbox

[1/2] error: Distinguish critical and non-critical errors

Message ID 1350667146-26273-2-git-send-email-peter.maydell@linaro.org
State New
Headers show

Commit Message

Peter Maydell Oct. 19, 2012, 5:19 p.m. UTC
Add the concept of a 'critical' error, which is one that must not
be ignored. If, at the point when the error is raised or at any
subsequent point while propagating it, we find that we would be
throwing away the error because of a NULL Error**, we print
the error message to stderr and abort().

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 error.c |   38 ++++++++++++++++++++++++++++++++++----
 error.h |   12 ++++++++++++
 2 files changed, 46 insertions(+), 4 deletions(-)
diff mbox

Patch

diff --git a/error.c b/error.c
index 1f05fc4..3f76fd5 100644
--- a/error.c
+++ b/error.c
@@ -21,12 +21,13 @@  struct Error
 {
     char *msg;
     ErrorClass err_class;
+    bool is_critical;
 };
 
-void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
+static void do_error_set(Error **errp, ErrorClass err_class,
+                         const char *fmt, va_list ap)
 {
     Error *err;
-    va_list ap;
 
     if (errp == NULL) {
         return;
@@ -35,14 +36,38 @@  void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
 
     err = g_malloc0(sizeof(*err));
 
-    va_start(ap, fmt);
     err->msg = g_strdup_vprintf(fmt, ap);
-    va_end(ap);
     err->err_class = err_class;
 
     *errp = err;
 }
 
+void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    do_error_set(errp, err_class, fmt, ap);
+    va_end(ap);
+}
+
+void error_set_critical(Error **errp, ErrorClass err_class,
+                        const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    if (!errp) {
+        /* Critical error which would be ignored: print and abort now */
+        vfprintf(stderr, fmt, ap);
+        fputc('\n', stderr);
+        abort();
+    }
+
+    do_error_set(errp, err_class, fmt, ap);
+    (*errp)->is_critical = true;
+
+    va_end(ap);
+}
+
 Error *error_copy(const Error *err)
 {
     Error *err_new;
@@ -50,6 +75,7 @@  Error *error_copy(const Error *err)
     err_new = g_malloc0(sizeof(*err));
     err_new->msg = g_strdup(err->msg);
     err_new->err_class = err->err_class;
+    err_new->is_critical = err->is_critical;
 
     return err_new;
 }
@@ -82,6 +108,10 @@  void error_propagate(Error **dst_err, Error *local_err)
     if (dst_err && !*dst_err) {
         *dst_err = local_err;
     } else if (local_err) {
+        if (local_err->is_critical) {
+            fprintf(stderr, "%s\n", error_get_pretty(local_err));
+            abort();
+        }
         error_free(local_err);
     }
 }
diff --git a/error.h b/error.h
index da7fed3..4be0893 100644
--- a/error.h
+++ b/error.h
@@ -36,6 +36,18 @@  void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_
     error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
 
 /**
+ * Same as error_set(), but mark the error as critical
+ */
+void error_set_critical(Error **err, ErrorClass err_class,
+                        const char *fmt, ...) GCC_FMT_ATTR(3, 4);
+
+/**
+ * Same as error_setg(), but mark the error as critical
+ */
+#define error_setg_critical(err, fmt, ...) \
+    error_set_critical(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
+
+/**
  * Returns true if an indirect pointer to an error is pointing to a valid
  * error object.
  */