Patchwork qdev: add return value to init() callbacks.

login
register
mail settings
Submitter Gerd Hoffmann
Date Aug. 13, 2009, 2:31 p.m.
Message ID <4A8423CA.2050108@redhat.com>
Download mbox | patch
Permalink /patch/31333/
State Superseded
Headers show

Comments

Gerd Hoffmann - Aug. 13, 2009, 2:31 p.m.
>      save output object
>      set up output object to point to the appropriate sink
>      call stuff (may print messages via output object to sink)
>      restore output object

i.e. something like the attached patch?

(qemu-kvm might need some more care due to the io thread).

cheers,
   Gerd
Markus Armbruster - Aug. 13, 2009, 5:22 p.m.
Gerd Hoffmann <kraxel@redhat.com> writes:

>>      save output object
>>      set up output object to point to the appropriate sink
>>      call stuff (may print messages via output object to sink)
>>      restore output object
>
> i.e. something like the attached patch?

Yes, that's the method I have in mind...

> (qemu-kvm might need some more care due to the io thread).

... modulo multi-threading.

Patch

diff --git a/monitor.c b/monitor.c
index 362322b..7163d21 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2839,6 +2839,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;
@@ -2890,8 +2891,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]);
@@ -3256,3 +3259,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 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(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;
+    }
+}
diff --git a/sysemu.h b/sysemu.h
index dffb2f1..1875bf7 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -65,6 +65,11 @@  int qemu_savevm_state_complete(QEMUFile *f);
 int qemu_savevm_state(QEMUFile *f);
 int qemu_loadvm_state(QEMUFile *f);
 
+void qemu_errors_to_file(FILE *fp);
+void qemu_errors_to_mon(Monitor *mon);
+void qemu_errors_to_previous(void);
+void qemu_error(char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+
 #ifdef _WIN32
 /* Polling handling */
 
diff --git a/vl.c b/vl.c
index 8b2b289..c1b11cd 100644
--- a/vl.c
+++ b/vl.c
@@ -4815,6 +4815,7 @@  int main(int argc, char **argv, char **envp)
     CPUState *env;
     int show_vnc_port = 0;
 
+    qemu_errors_to_file(stderr);
     qemu_cache_utils_init(envp);
 
     LIST_INIT (&vm_change_state_head);