Patchwork [5/9] monitor: QError support

login
register
mail settings
Submitter Luiz Capitulino
Date Oct. 13, 2009, 4:57 p.m.
Message ID <1255453026-18637-6-git-send-email-lcapitulino@redhat.com>
Download mbox | patch
Permalink /patch/35877/
State New
Headers show

Comments

Luiz Capitulino - Oct. 13, 2009, 4:57 p.m.
This commit paves the way for QError support in the Monitor,
it adds a QError member to the Monitor struct and functions
to check and print it.

Additionally, it introduces qemu_error_structed() which should
be used by functions that are called by monitor handlers and
print error information.

This new function has to be used in place of qemu_error(), which
will become private when all the conversion is done.

Basically, the Monitor's error flow is something like this:

1. An error happens in the handler, it calls qemu_error_structed()
2. qemu_error_structed() builds the right QObjects with the error
   information and stores them in the Monitor struct
3. The handler returns
4. Top level Monitor code checks the Monitor struct and calls
   qerror_print() to print the error

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 monitor.c |   44 +++++++++++++++++++++++++++++++++++++++++++-
 sysemu.h  |    2 ++
 2 files changed, 45 insertions(+), 1 deletions(-)
Markus Armbruster - Oct. 13, 2009, 9:59 p.m.
Luiz Capitulino <lcapitulino@redhat.com> writes:

> This commit paves the way for QError support in the Monitor,
> it adds a QError member to the Monitor struct and functions
> to check and print it.
>
> Additionally, it introduces qemu_error_structed() which should
> be used by functions that are called by monitor handlers and
> print error information.
>
> This new function has to be used in place of qemu_error(), which
> will become private when all the conversion is done.
>
> Basically, the Monitor's error flow is something like this:
>
> 1. An error happens in the handler, it calls qemu_error_structed()
> 2. qemu_error_structed() builds the right QObjects with the error
>    information and stores them in the Monitor struct
> 3. The handler returns
> 4. Top level Monitor code checks the Monitor struct and calls
>    qerror_print() to print the error
[...]
> diff --git a/sysemu.h b/sysemu.h
> index 896916f..02247fe 100644
> --- a/sysemu.h
> +++ b/sysemu.h
> @@ -7,6 +7,7 @@
>  #include "qemu-queue.h"
>  #include "qemu-timer.h"
>  #include "qdict.h"
> +#include "qerror.h"
>  
>  #ifdef _WIN32
>  #include <windows.h>
> @@ -70,6 +71,7 @@ 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_structed(QErrorCode code, const char *fmt, ...);

Needs __attribute__((format(printf, 2, 3))).

>  void qemu_error(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
>  
>  #ifdef _WIN32
Paolo Bonzini - Oct. 14, 2009, 1:14 p.m.
On 10/13/2009 11:59 PM, Markus Armbruster wrote:
>> >  +void qemu_error_structed(QErrorCode code, const char *fmt, ...);
> Needs __attribute__((format(printf, 2, 3))).

If I read the code correctly, qemu_object_from_va is what in the end 
processes the valist and it is not exactly compatible with printf 
syntax.  For example, in patch 7/9 you have

      qemu_error_structed(QERR_QDEV_NFOUND, "{ s: s }", "name", driver);

Paolo
Markus Armbruster - Oct. 14, 2009, 2:07 p.m.
Paolo Bonzini <pbonzini@redhat.com> writes:

> On 10/13/2009 11:59 PM, Markus Armbruster wrote:
>>> >  +void qemu_error_structed(QErrorCode code, const char *fmt, ...);
>> Needs __attribute__((format(printf, 2, 3))).
>
> If I read the code correctly, qemu_object_from_va is what in the end
> processes the valist and it is not exactly compatible with printf
> syntax.  For example, in patch 7/9 you have
>
>      qemu_error_structed(QERR_QDEV_NFOUND, "{ s: s }", "name", driver);

You're right, of course.

Pity we lose the checking.

Patch

diff --git a/monitor.c b/monitor.c
index 39d3201..6f0ad11 100644
--- a/monitor.c
+++ b/monitor.c
@@ -49,6 +49,7 @@ 
 #include "qlist.h"
 #include "qdict.h"
 #include "qstring.h"
+#include "qerror.h"
 
 //#define DEBUG
 //#define DEBUG_COMPLETION
@@ -103,6 +104,7 @@  struct Monitor {
     CPUState *mon_cpu;
     BlockDriverCompletionFunc *password_completion_cb;
     void *password_opaque;
+    QError *error;
     QLIST_HEAD(,mon_fd_t) fds;
     QLIST_ENTRY(Monitor) entry;
 };
@@ -3148,6 +3150,18 @@  fail:
     return NULL;
 }
 
+static inline int monitor_has_error(const Monitor *mon)
+{
+    return mon->error != NULL;
+}
+
+static void monitor_print_error(Monitor *mon)
+{
+    qerror_print(mon->error);
+    QDECREF(mon->error);
+    mon->error = NULL;
+}
+
 static void monitor_handle_command(Monitor *mon, const char *cmdline)
 {
     QDict *qdict;
@@ -3173,7 +3187,10 @@  static void monitor_handle_command(Monitor *mon, const char *cmdline)
         cmd->mhandler.cmd(mon, qdict);
     }
 
-   qemu_errors_to_previous();
+    if (monitor_has_error(mon))
+        monitor_print_error(mon);
+
+    qemu_errors_to_previous();
 
 out:
     QDECREF(qdict);
@@ -3624,3 +3641,28 @@  void qemu_error(const char *fmt, ...)
         break;
     }
 }
+
+void qemu_error_structed(QErrorCode code, const char *fmt, ...)
+{
+    va_list va;
+    QError *qerror;
+
+    assert(qemu_error_sink != NULL);
+
+    va_start(va, fmt);
+    qerror = qerror_from_va(code, fmt, va);
+    va_end(va);
+
+    assert(qerror != NULL);
+
+    switch (qemu_error_sink->dest) {
+    case ERR_SINK_FILE:
+        qerror_print(qerror);
+        QDECREF(qerror);
+        break;
+    case ERR_SINK_MONITOR:
+        assert(qemu_error_sink->mon->error == NULL);
+        qemu_error_sink->mon->error = qerror;
+        break;
+    }
+}
diff --git a/sysemu.h b/sysemu.h
index 896916f..02247fe 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -7,6 +7,7 @@ 
 #include "qemu-queue.h"
 #include "qemu-timer.h"
 #include "qdict.h"
+#include "qerror.h"
 
 #ifdef _WIN32
 #include <windows.h>
@@ -70,6 +71,7 @@  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_structed(QErrorCode code, const char *fmt, ...);
 void qemu_error(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
 
 #ifdef _WIN32