@@ -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);
}
}
@@ -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.
*/
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(-)