2011-06-01 17:14:49 +00:00
|
|
|
/*
|
|
|
|
* QEMU Error Objects
|
|
|
|
*
|
|
|
|
* Copyright IBM, Corp. 2011
|
2015-09-11 14:51:42 +00:00
|
|
|
* Copyright (C) 2011-2015 Red Hat, Inc.
|
2011-06-01 17:14:49 +00:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Anthony Liguori <aliguori@us.ibm.com>
|
2015-09-11 14:51:42 +00:00
|
|
|
* Markus Armbruster <armbru@redhat.com>,
|
2011-06-01 17:14:49 +00:00
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU LGPL, version 2. See
|
|
|
|
* the COPYING.LIB file in the top-level directory.
|
|
|
|
*/
|
2011-06-13 21:01:53 +00:00
|
|
|
|
2016-01-29 17:49:55 +00:00
|
|
|
#include "qemu/osdep.h"
|
2011-06-13 21:01:53 +00:00
|
|
|
#include "qemu-common.h"
|
2014-03-21 23:42:28 +00:00
|
|
|
#include "qemu/error-report.h"
|
2011-06-01 17:14:49 +00:00
|
|
|
|
|
|
|
struct Error
|
|
|
|
{
|
|
|
|
char *msg;
|
2012-07-27 17:09:29 +00:00
|
|
|
ErrorClass err_class;
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
const char *src, *func;
|
|
|
|
int line;
|
hmp: Allow for error message hints on HMP
Commits 7216ae3d and d2828429 disabled some error message hints,
all because a change to use modern error reporting meant that the
hint would be output prior to the actual error. Fix this by making
hints a first-class member of Error.
For example, we are now back to the pleasant:
$ qemu-system-x86_64 --nodefaults -S --vnc :0 --chardev null,id=,
qemu-system-x86_64: --chardev null,id=,: Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1441901956-21991-1-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-09-10 16:19:16 +00:00
|
|
|
GString *hint;
|
2011-06-01 17:14:49 +00:00
|
|
|
};
|
|
|
|
|
2014-01-02 02:46:59 +00:00
|
|
|
Error *error_abort;
|
2015-09-11 14:51:42 +00:00
|
|
|
Error *error_fatal;
|
2014-01-02 02:46:59 +00:00
|
|
|
|
2015-09-11 14:51:42 +00:00
|
|
|
static void error_handle_fatal(Error **errp, Error *err)
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
{
|
2015-09-11 14:51:42 +00:00
|
|
|
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);
|
|
|
|
}
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void error_setv(Error **errp,
|
|
|
|
const char *src, int line, const char *func,
|
2016-03-09 17:28:24 +00:00
|
|
|
ErrorClass err_class, const char *fmt, va_list ap,
|
|
|
|
const char *suffix)
|
2011-06-01 17:14:49 +00:00
|
|
|
{
|
|
|
|
Error *err;
|
2013-11-07 19:10:29 +00:00
|
|
|
int saved_errno = errno;
|
2011-06-01 17:14:49 +00:00
|
|
|
|
|
|
|
if (errp == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2012-07-17 14:17:04 +00:00
|
|
|
assert(*errp == NULL);
|
2011-06-01 17:14:49 +00:00
|
|
|
|
2011-08-21 03:09:37 +00:00
|
|
|
err = g_malloc0(sizeof(*err));
|
2012-07-27 20:51:03 +00:00
|
|
|
err->msg = g_strdup_vprintf(fmt, ap);
|
2016-03-09 17:28:24 +00:00
|
|
|
if (suffix) {
|
|
|
|
char *msg = err->msg;
|
|
|
|
err->msg = g_strdup_printf("%s: %s", msg, suffix);
|
|
|
|
g_free(msg);
|
|
|
|
}
|
2012-07-27 17:09:29 +00:00
|
|
|
err->err_class = err_class;
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
err->src = src;
|
|
|
|
err->line = line;
|
|
|
|
err->func = func;
|
2011-06-01 17:14:49 +00:00
|
|
|
|
2015-09-11 14:51:42 +00:00
|
|
|
error_handle_fatal(errp, err);
|
2011-06-01 17:14:49 +00:00
|
|
|
*errp = err;
|
2013-11-07 19:10:29 +00:00
|
|
|
|
|
|
|
errno = saved_errno;
|
2011-06-01 17:14:49 +00:00
|
|
|
}
|
|
|
|
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
void error_set_internal(Error **errp,
|
|
|
|
const char *src, int line, const char *func,
|
|
|
|
ErrorClass err_class, const char *fmt, ...)
|
2015-06-19 11:59:47 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2016-03-09 17:28:24 +00:00
|
|
|
error_setv(errp, src, line, func, err_class, fmt, ap, NULL);
|
2015-06-19 11:59:47 +00:00
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
void error_setg_internal(Error **errp,
|
|
|
|
const char *src, int line, const char *func,
|
|
|
|
const char *fmt, ...)
|
2015-06-19 13:36:16 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2016-03-09 17:28:24 +00:00
|
|
|
error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL);
|
2015-06-19 13:36:16 +00:00
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
void error_setg_errno_internal(Error **errp,
|
|
|
|
const char *src, int line, const char *func,
|
|
|
|
int os_errno, const char *fmt, ...)
|
2012-10-02 07:00:45 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
2013-11-07 19:10:29 +00:00
|
|
|
int saved_errno = errno;
|
2012-10-02 07:00:45 +00:00
|
|
|
|
|
|
|
if (errp == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2016-03-09 17:28:24 +00:00
|
|
|
error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap,
|
|
|
|
os_errno != 0 ? strerror(os_errno) : NULL);
|
2012-10-02 07:00:45 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
2013-11-07 19:10:29 +00:00
|
|
|
errno = saved_errno;
|
2012-10-02 07:00:45 +00:00
|
|
|
}
|
|
|
|
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
void error_setg_file_open_internal(Error **errp,
|
|
|
|
const char *src, int line, const char *func,
|
|
|
|
int os_errno, const char *filename)
|
2013-06-07 18:24:49 +00:00
|
|
|
{
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
error_setg_errno_internal(errp, src, line, func, os_errno,
|
|
|
|
"Could not open '%s'", filename);
|
2013-06-07 18:24:49 +00:00
|
|
|
}
|
|
|
|
|
error: New error_prepend(), error_reportf_err()
Instead of simply propagating an error verbatim, we sometimes want to
add to its message, like this:
frobnicate(arg, &err);
error_setg(errp, "Can't frobnicate %s: %s",
arg, error_get_pretty(err));
error_free(err);
This is suboptimal, because it loses err's hint (if any). Moreover,
when errp is &error_abort or is subsequently propagated to
&error_abort, the abort message points to the place where we last
added to the error, not to the place where it originated.
To avoid these issues, provide means to add to an error's message in
place:
frobnicate(arg, errp);
error_prepend(errp, "Can't frobnicate %s: ", arg);
Likewise, reporting an error like
frobnicate(arg, &err);
error_report("Can't frobnicate %s: %s", arg, error_get_pretty(err));
can lose err's hint. To avoid:
error_reportf_err(err, "Can't frobnicate %s: ", arg);
The next commits will put these functions to use.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-10-git-send-email-armbru@redhat.com>
2015-12-18 15:35:12 +00:00
|
|
|
void error_vprepend(Error **errp, const char *fmt, va_list ap)
|
|
|
|
{
|
|
|
|
GString *newmsg;
|
|
|
|
|
|
|
|
if (!errp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
newmsg = g_string_new(NULL);
|
|
|
|
g_string_vprintf(newmsg, fmt, ap);
|
|
|
|
g_string_append(newmsg, (*errp)->msg);
|
|
|
|
(*errp)->msg = g_string_free(newmsg, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void error_prepend(Error **errp, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
error_vprepend(errp, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
hmp: Allow for error message hints on HMP
Commits 7216ae3d and d2828429 disabled some error message hints,
all because a change to use modern error reporting meant that the
hint would be output prior to the actual error. Fix this by making
hints a first-class member of Error.
For example, we are now back to the pleasant:
$ qemu-system-x86_64 --nodefaults -S --vnc :0 --chardev null,id=,
qemu-system-x86_64: --chardev null,id=,: Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1441901956-21991-1-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-09-10 16:19:16 +00:00
|
|
|
void error_append_hint(Error **errp, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
int saved_errno = errno;
|
|
|
|
Error *err;
|
|
|
|
|
|
|
|
if (!errp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
err = *errp;
|
2015-12-18 15:35:08 +00:00
|
|
|
assert(err && errp != &error_abort && errp != &error_fatal);
|
hmp: Allow for error message hints on HMP
Commits 7216ae3d and d2828429 disabled some error message hints,
all because a change to use modern error reporting meant that the
hint would be output prior to the actual error. Fix this by making
hints a first-class member of Error.
For example, we are now back to the pleasant:
$ qemu-system-x86_64 --nodefaults -S --vnc :0 --chardev null,id=,
qemu-system-x86_64: --chardev null,id=,: Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1441901956-21991-1-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-09-10 16:19:16 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-08-07 15:40:11 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
|
error: On abort, report where the error was created
This is particularly useful when we abort in error_propagate(),
because there the stack backtrace doesn't lead to where the error was
created. Looks like this:
Unexpected error in parse_block_error_action() at .../qemu/blockdev.c:322:
qemu-system-x86_64: -drive if=none,werror=foo: 'foo' invalid write error action
Aborted (core dumped)
Note: to get this example output, I monkey-patched drive_new() to pass
&error_abort to blockdev_init().
To keep the error handling boiler plate from growing even more, all
error_setFOO() become macros expanding into error_setFOO_internal()
with additional __FILE__, __LINE__, __func__ arguments. Not exactly
pretty, but it works.
The macro trickery breaks down when you take the address of an
error_setFOO(). Fortunately, we do that in just one place: qemu-ga's
Windows VSS provider and requester DLL wants to call
error_setg_win32() through a function pointer "to avoid linking glib
to the DLL". Use error_setg_win32_internal() there. The use of the
function pointer is already wrapped in a macro, so the churn isn't
bad.
Code size increases by some 35KiB for me (0.7%). Tolerable. Could be
less if we passed relative rather than absolute source file names to
the compiler, or forwent reporting __func__.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-19 17:21:59 +00:00
|
|
|
void error_setg_win32_internal(Error **errp,
|
|
|
|
const char *src, int line, const char *func,
|
|
|
|
int win32_err, const char *fmt, ...)
|
2013-08-07 15:40:11 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
2016-03-09 17:28:24 +00:00
|
|
|
char *suffix = NULL;
|
2013-08-07 15:40:11 +00:00
|
|
|
|
|
|
|
if (errp == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-09 17:28:24 +00:00
|
|
|
if (win32_err != 0) {
|
|
|
|
suffix = g_win32_error_message(win32_err);
|
|
|
|
}
|
|
|
|
|
2013-08-07 15:40:11 +00:00
|
|
|
va_start(ap, fmt);
|
2016-03-09 17:28:24 +00:00
|
|
|
error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR,
|
|
|
|
fmt, ap, suffix);
|
2015-06-19 11:59:47 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
2016-03-09 17:28:24 +00:00
|
|
|
g_free(suffix);
|
2013-08-07 15:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2011-12-05 18:04:05 +00:00
|
|
|
Error *error_copy(const Error *err)
|
|
|
|
{
|
|
|
|
Error *err_new;
|
|
|
|
|
|
|
|
err_new = g_malloc0(sizeof(*err));
|
|
|
|
err_new->msg = g_strdup(err->msg);
|
2012-07-27 17:09:29 +00:00
|
|
|
err_new->err_class = err->err_class;
|
2015-09-10 16:34:50 +00:00
|
|
|
err_new->src = err->src;
|
|
|
|
err_new->line = err->line;
|
|
|
|
err_new->func = err->func;
|
hmp: Allow for error message hints on HMP
Commits 7216ae3d and d2828429 disabled some error message hints,
all because a change to use modern error reporting meant that the
hint would be output prior to the actual error. Fix this by making
hints a first-class member of Error.
For example, we are now back to the pleasant:
$ qemu-system-x86_64 --nodefaults -S --vnc :0 --chardev null,id=,
qemu-system-x86_64: --chardev null,id=,: Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1441901956-21991-1-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-09-10 16:19:16 +00:00
|
|
|
if (err->hint) {
|
|
|
|
err_new->hint = g_string_new(err->hint->str);
|
|
|
|
}
|
2011-12-05 18:04:05 +00:00
|
|
|
|
|
|
|
return err_new;
|
|
|
|
}
|
|
|
|
|
2012-08-01 19:29:38 +00:00
|
|
|
ErrorClass error_get_class(const Error *err)
|
|
|
|
{
|
|
|
|
return err->err_class;
|
|
|
|
}
|
|
|
|
|
2011-06-01 17:14:49 +00:00
|
|
|
const char *error_get_pretty(Error *err)
|
|
|
|
{
|
|
|
|
return err->msg;
|
|
|
|
}
|
|
|
|
|
2015-02-06 14:27:19 +00:00
|
|
|
void error_report_err(Error *err)
|
|
|
|
{
|
|
|
|
error_report("%s", error_get_pretty(err));
|
hmp: Allow for error message hints on HMP
Commits 7216ae3d and d2828429 disabled some error message hints,
all because a change to use modern error reporting meant that the
hint would be output prior to the actual error. Fix this by making
hints a first-class member of Error.
For example, we are now back to the pleasant:
$ qemu-system-x86_64 --nodefaults -S --vnc :0 --chardev null,id=,
qemu-system-x86_64: --chardev null,id=,: Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1441901956-21991-1-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-09-10 16:19:16 +00:00
|
|
|
if (err->hint) {
|
2015-12-17 16:35:14 +00:00
|
|
|
error_printf_unless_qmp("%s", err->hint->str);
|
hmp: Allow for error message hints on HMP
Commits 7216ae3d and d2828429 disabled some error message hints,
all because a change to use modern error reporting meant that the
hint would be output prior to the actual error. Fix this by making
hints a first-class member of Error.
For example, we are now back to the pleasant:
$ qemu-system-x86_64 --nodefaults -S --vnc :0 --chardev null,id=,
qemu-system-x86_64: --chardev null,id=,: Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1441901956-21991-1-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-09-10 16:19:16 +00:00
|
|
|
}
|
2015-02-06 14:27:19 +00:00
|
|
|
error_free(err);
|
|
|
|
}
|
|
|
|
|
error: New error_prepend(), error_reportf_err()
Instead of simply propagating an error verbatim, we sometimes want to
add to its message, like this:
frobnicate(arg, &err);
error_setg(errp, "Can't frobnicate %s: %s",
arg, error_get_pretty(err));
error_free(err);
This is suboptimal, because it loses err's hint (if any). Moreover,
when errp is &error_abort or is subsequently propagated to
&error_abort, the abort message points to the place where we last
added to the error, not to the place where it originated.
To avoid these issues, provide means to add to an error's message in
place:
frobnicate(arg, errp);
error_prepend(errp, "Can't frobnicate %s: ", arg);
Likewise, reporting an error like
frobnicate(arg, &err);
error_report("Can't frobnicate %s: %s", arg, error_get_pretty(err));
can lose err's hint. To avoid:
error_reportf_err(err, "Can't frobnicate %s: ", arg);
The next commits will put these functions to use.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-10-git-send-email-armbru@redhat.com>
2015-12-18 15:35:12 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-06-01 17:14:49 +00:00
|
|
|
void error_free(Error *err)
|
|
|
|
{
|
|
|
|
if (err) {
|
2011-08-21 03:09:37 +00:00
|
|
|
g_free(err->msg);
|
hmp: Allow for error message hints on HMP
Commits 7216ae3d and d2828429 disabled some error message hints,
all because a change to use modern error reporting meant that the
hint would be output prior to the actual error. Fix this by making
hints a first-class member of Error.
For example, we are now back to the pleasant:
$ qemu-system-x86_64 --nodefaults -S --vnc :0 --chardev null,id=,
qemu-system-x86_64: --chardev null,id=,: Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1441901956-21991-1-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-09-10 16:19:16 +00:00
|
|
|
if (err->hint) {
|
|
|
|
g_string_free(err->hint, true);
|
|
|
|
}
|
2011-08-21 03:09:37 +00:00
|
|
|
g_free(err);
|
2011-06-01 17:14:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-06 06:35:31 +00:00
|
|
|
void error_free_or_abort(Error **errp)
|
|
|
|
{
|
|
|
|
assert(errp && *errp);
|
|
|
|
error_free(*errp);
|
|
|
|
*errp = NULL;
|
|
|
|
}
|
|
|
|
|
2014-05-02 11:26:32 +00:00
|
|
|
void error_propagate(Error **dst_errp, Error *local_err)
|
2011-06-01 17:14:49 +00:00
|
|
|
{
|
2015-09-11 14:51:42 +00:00
|
|
|
if (!local_err) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
error_handle_fatal(dst_errp, local_err);
|
|
|
|
if (dst_errp && !*dst_errp) {
|
2014-05-02 11:26:32 +00:00
|
|
|
*dst_errp = local_err;
|
2015-09-11 14:51:42 +00:00
|
|
|
} else {
|
2011-06-01 17:14:49 +00:00
|
|
|
error_free(local_err);
|
|
|
|
}
|
|
|
|
}
|