X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Futil%2Ferror.c;fp=qemu%2Futil%2Ferror.c;h=cae2511732b93b50470a8439d7d3aaa31db79af1;hb=437fd90c0250dee670290f9b714253671a990160;hp=14f43518792e3debe3381bf73ab035663fded4e2;hpb=5bbd6fe9b8bab2a93e548c5a53b032d1939eec05;p=kvmfornfv.git diff --git a/qemu/util/error.c b/qemu/util/error.c index 14f435187..cae251173 100644 --- a/qemu/util/error.c +++ b/qemu/util/error.c @@ -2,30 +2,53 @@ * QEMU Error Objects * * Copyright IBM, Corp. 2011 + * Copyright (C) 2011-2015 Red Hat, Inc. * * Authors: * Anthony Liguori + * Markus Armbruster , * * This work is licensed under the terms of the GNU LGPL, version 2. See * the COPYING.LIB file in the top-level directory. */ -#include "qemu-common.h" +#include "qemu/osdep.h" #include "qapi/error.h" +#include "qemu-common.h" #include "qemu/error-report.h" struct Error { char *msg; ErrorClass err_class; + const char *src, *func; + int line; + GString *hint; }; Error *error_abort; +Error *error_fatal; + +static void error_handle_fatal(Error **errp, Error *err) +{ + if (errp == &error_abort) { + fprintf(stderr, "Unexpected error in %s() at %s:%d:\n", + err->func, err->src, err->line); + error_report_err(err); + abort(); + } + if (errp == &error_fatal) { + error_report_err(err); + exit(1); + } +} -void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...) +static void error_setv(Error **errp, + const char *src, int line, const char *func, + ErrorClass err_class, const char *fmt, va_list ap, + const char *suffix) { Error *err; - va_list ap; int saved_errno = errno; if (errp == NULL) { @@ -34,99 +57,140 @@ void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...) assert(*errp == NULL); err = g_malloc0(sizeof(*err)); - - va_start(ap, fmt); err->msg = g_strdup_vprintf(fmt, ap); - va_end(ap); - err->err_class = err_class; - - if (errp == &error_abort) { - error_report_err(err); - abort(); + if (suffix) { + char *msg = err->msg; + err->msg = g_strdup_printf("%s: %s", msg, suffix); + g_free(msg); } + err->err_class = err_class; + err->src = src; + err->line = line; + err->func = func; + error_handle_fatal(errp, err); *errp = err; errno = saved_errno; } -void error_set_errno(Error **errp, int os_errno, ErrorClass err_class, - const char *fmt, ...) +void error_set_internal(Error **errp, + const char *src, int line, const char *func, + ErrorClass err_class, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_setv(errp, src, line, func, err_class, fmt, ap, NULL); + va_end(ap); +} + +void error_setg_internal(Error **errp, + const char *src, int line, const char *func, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL); + va_end(ap); +} + +void error_setg_errno_internal(Error **errp, + const char *src, int line, const char *func, + int os_errno, const char *fmt, ...) { - Error *err; - char *msg1; va_list ap; int saved_errno = errno; if (errp == NULL) { return; } - assert(*errp == NULL); - - err = g_malloc0(sizeof(*err)); va_start(ap, fmt); - msg1 = g_strdup_vprintf(fmt, ap); - if (os_errno != 0) { - err->msg = g_strdup_printf("%s: %s", msg1, strerror(os_errno)); - g_free(msg1); - } else { - err->msg = msg1; - } + error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, + os_errno != 0 ? strerror(os_errno) : NULL); va_end(ap); - err->err_class = err_class; - if (errp == &error_abort) { - error_report_err(err); - abort(); + errno = saved_errno; +} + +void error_setg_file_open_internal(Error **errp, + const char *src, int line, const char *func, + int os_errno, const char *filename) +{ + error_setg_errno_internal(errp, src, line, func, os_errno, + "Could not open '%s'", filename); +} + +void error_vprepend(Error **errp, const char *fmt, va_list ap) +{ + GString *newmsg; + + if (!errp) { + return; } - *errp = err; + newmsg = g_string_new(NULL); + g_string_vprintf(newmsg, fmt, ap); + g_string_append(newmsg, (*errp)->msg); + (*errp)->msg = g_string_free(newmsg, 0); +} - errno = saved_errno; +void error_prepend(Error **errp, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_vprepend(errp, fmt, ap); + va_end(ap); } -void error_setg_file_open(Error **errp, int os_errno, const char *filename) +void error_append_hint(Error **errp, const char *fmt, ...) { - error_setg_errno(errp, os_errno, "Could not open '%s'", filename); + va_list ap; + int saved_errno = errno; + Error *err; + + if (!errp) { + return; + } + err = *errp; + assert(err && errp != &error_abort && errp != &error_fatal); + + if (!err->hint) { + err->hint = g_string_new(NULL); + } + va_start(ap, fmt); + g_string_append_vprintf(err->hint, fmt, ap); + va_end(ap); + + errno = saved_errno; } #ifdef _WIN32 -void error_set_win32(Error **errp, int win32_err, ErrorClass err_class, - const char *fmt, ...) +void error_setg_win32_internal(Error **errp, + const char *src, int line, const char *func, + int win32_err, const char *fmt, ...) { - Error *err; - char *msg1; va_list ap; + char *suffix = NULL; if (errp == NULL) { return; } - assert(*errp == NULL); - err = g_malloc0(sizeof(*err)); - - va_start(ap, fmt); - msg1 = g_strdup_vprintf(fmt, ap); if (win32_err != 0) { - char *msg2 = g_win32_error_message(win32_err); - err->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2, - (unsigned)win32_err); - g_free(msg2); - g_free(msg1); - } else { - err->msg = msg1; + suffix = g_win32_error_message(win32_err); } - va_end(ap); - err->err_class = err_class; - if (errp == &error_abort) { - error_report_err(err); - abort(); - } + va_start(ap, fmt); + error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, + fmt, ap, suffix); + va_end(ap); - *errp = err; + g_free(suffix); } #endif @@ -138,6 +202,12 @@ 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->src = err->src; + err_new->line = err->line; + err_new->func = err->func; + if (err->hint) { + err_new->hint = g_string_new(err->hint->str); + } return err_new; } @@ -155,25 +225,49 @@ const char *error_get_pretty(Error *err) void error_report_err(Error *err) { error_report("%s", error_get_pretty(err)); + if (err->hint) { + error_printf_unless_qmp("%s", err->hint->str); + } error_free(err); } +void error_reportf_err(Error *err, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_vprepend(&err, fmt, ap); + va_end(ap); + error_report_err(err); +} + void error_free(Error *err) { if (err) { g_free(err->msg); + if (err->hint) { + g_string_free(err->hint, true); + } g_free(err); } } +void error_free_or_abort(Error **errp) +{ + assert(errp && *errp); + error_free(*errp); + *errp = NULL; +} + 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) { + if (!local_err) { + return; + } + error_handle_fatal(dst_errp, local_err); + if (dst_errp && !*dst_errp) { *dst_errp = local_err; - } else if (local_err) { + } else { error_free(local_err); } }