aboutsummaryrefslogtreecommitdiff
path: root/monitor.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2009-08-14 10:36:06 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-08-27 20:43:33 -0500
commitac7531ecdc8349ffc3a8d85721218df5585e30b6 (patch)
tree61b23e3a7f491b9f5939f03ab77527e9183be0cb /monitor.c
parent81a322d4a1b68d47908a6630bf22897a289722aa (diff)
add qemu_error() + friends
This patch adds some functions for error reporting to address the problem that error messages should be routed to different destinations depending on the context of the caller, i.e. monitor command errors should go to the monitor, command line errors to stderr. qemu_error() is a printf-like function to report errors. qemu_errors_to_file() and qemu_errors_to_mon() switch the destination for the error message to the specified file or monitor. When setting a new destination the old one will be kept. One can switch back using qemu_errors_to_previous(). i.e. it works like a stack. main() calls qemu_errors_to_file(stderr), so errors go to stderr by default. monitor callbacks are wrapped into qemu_errors_to_mon() + qemu_errors_to_previous(), so any errors triggered by monitor commands will go to the monitor. Each thread has its own error message destination. qemu-kvm probably should add a qemu_errors_to_file(stderr) call to the i/o-thread initialization code. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'monitor.c')
-rw-r--r--monitor.c71
1 files changed, 70 insertions, 1 deletions
diff --git a/monitor.c b/monitor.c
index ca1731eddc..2559a62597 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2792,6 +2792,7 @@ static void monitor_handle_command(Monitor *mon, const char *cmdline)
goto fail;
}
+ qemu_errors_to_mon(mon);
switch(nb_args) {
case 0:
handler_0 = cmd->handler;
@@ -2843,8 +2844,10 @@ static void monitor_handle_command(Monitor *mon, const char *cmdline)
break;
default:
monitor_printf(mon, "unsupported number of arguments: %d\n", nb_args);
- goto fail;
+ break;
}
+ qemu_errors_to_previous();
+
fail:
for(i = 0; i < MAX_ARGS; i++)
qemu_free(str_allocated[i]);
@@ -3212,3 +3215,69 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
if (err && completion_cb)
completion_cb(opaque, err);
}
+
+typedef struct QemuErrorSink QemuErrorSink;
+struct QemuErrorSink {
+ enum {
+ ERR_SINK_FILE,
+ ERR_SINK_MONITOR,
+ } dest;
+ union {
+ FILE *fp;
+ Monitor *mon;
+ };
+ QemuErrorSink *previous;
+};
+
+static __thread QemuErrorSink *qemu_error_sink;
+
+void qemu_errors_to_file(FILE *fp)
+{
+ QemuErrorSink *sink;
+
+ sink = qemu_mallocz(sizeof(*sink));
+ sink->dest = ERR_SINK_FILE;
+ sink->fp = fp;
+ sink->previous = qemu_error_sink;
+ qemu_error_sink = sink;
+}
+
+void qemu_errors_to_mon(Monitor *mon)
+{
+ QemuErrorSink *sink;
+
+ sink = qemu_mallocz(sizeof(*sink));
+ sink->dest = ERR_SINK_MONITOR;
+ sink->mon = mon;
+ sink->previous = qemu_error_sink;
+ qemu_error_sink = sink;
+}
+
+void qemu_errors_to_previous(void)
+{
+ QemuErrorSink *sink;
+
+ assert(qemu_error_sink != NULL);
+ sink = qemu_error_sink;
+ qemu_error_sink = sink->previous;
+ qemu_free(sink);
+}
+
+void qemu_error(const char *fmt, ...)
+{
+ va_list args;
+
+ assert(qemu_error_sink != NULL);
+ switch (qemu_error_sink->dest) {
+ case ERR_SINK_FILE:
+ va_start(args, fmt);
+ vfprintf(qemu_error_sink->fp, fmt, args);
+ va_end(args);
+ break;
+ case ERR_SINK_MONITOR:
+ va_start(args, fmt);
+ monitor_vprintf(qemu_error_sink->mon, fmt, args);
+ va_end(args);
+ break;
+ }
+}