const char *params;
const char *help;
void (*user_print)(Monitor *mon, const QObject *data);
- int (*cmd_new_ret)(Monitor *mon, const QDict *params, QObject **ret_data);
union {
void (*info)(Monitor *mon);
void (*info_new)(Monitor *mon, QObject **ret_data);
int (*info_async)(Monitor *mon, MonitorCompletion *cb, void *opaque);
void (*cmd)(Monitor *mon, const QDict *qdict);
- void (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
+ int (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
int (*cmd_async)(Monitor *mon, const QDict *params,
MonitorCompletion *cb, void *opaque);
} mhandler;
typedef struct MonitorControl {
QObject *id;
- int print_enabled;
JSONMessageParser parser;
int command_mode;
} MonitorControl;
CPUState *mon_cpu;
BlockDriverCompletionFunc *password_completion_cb;
void *password_opaque;
+#ifdef CONFIG_DEBUG_MONITOR
+ int print_calls_nr;
+#endif
QError *error;
QLIST_HEAD(,mon_fd_t) fds;
QLIST_ENTRY(Monitor) entry;
};
+#ifdef CONFIG_DEBUG_MONITOR
+#define MON_DEBUG(fmt, ...) do { \
+ fprintf(stderr, "Monitor: "); \
+ fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+
+static inline void mon_print_count_inc(Monitor *mon)
+{
+ mon->print_calls_nr++;
+}
+
+static inline void mon_print_count_init(Monitor *mon)
+{
+ mon->print_calls_nr = 0;
+}
+
+static inline int mon_print_count_get(const Monitor *mon)
+{
+ return mon->print_calls_nr;
+}
+
+#else /* !CONFIG_DEBUG_MONITOR */
+#define MON_DEBUG(fmt, ...) do { } while (0)
+static inline void mon_print_count_inc(Monitor *mon) { }
+static inline void mon_print_count_init(Monitor *mon) { }
+static inline int mon_print_count_get(const Monitor *mon) { return 0; }
+#endif /* CONFIG_DEBUG_MONITOR */
+
static QLIST_HEAD(mon_list, Monitor) mon_list;
static const mon_cmd_t mon_cmds[];
static const mon_cmd_t info_cmds[];
-Monitor *cur_mon = NULL;
+Monitor *cur_mon;
+Monitor *default_mon;
static void monitor_command_cb(Monitor *mon, const char *cmdline,
void *opaque);
return (mon->flags & MONITOR_USE_CONTROL);
}
+/* Return non-zero iff we have a current monitor, and it is in QMP mode. */
+int monitor_cur_is_qmp(void)
+{
+ return cur_mon && monitor_ctrl_mode(cur_mon);
+}
+
static void monitor_read_command(Monitor *mon, int show_prompt)
{
if (!mon->rs)
void *opaque)
{
if (monitor_ctrl_mode(mon)) {
- qemu_error_new(QERR_MISSING_PARAMETER, "password");
+ qerror_report(QERR_MISSING_PARAMETER, "password");
return -EINVAL;
} else if (mon->rs) {
readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
{
+ char buf[4096];
+
if (!mon)
return;
- if (mon->mc && !mon->mc->print_enabled) {
- qemu_error_new(QERR_UNDEFINED_ERROR);
- } else {
- char buf[4096];
- vsnprintf(buf, sizeof(buf), fmt, ap);
- monitor_puts(mon, buf);
+ mon_print_count_inc(mon);
+
+ if (monitor_ctrl_mode(mon)) {
+ return;
}
+
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ monitor_puts(mon, buf);
}
void monitor_printf(Monitor *mon, const char *fmt, ...)
json = qobject_to_json(data);
assert(json != NULL);
- mon->mc->print_enabled = 1;
- monitor_printf(mon, "%s\n", qstring_get_str(json));
- mon->mc->print_enabled = 0;
+ qstring_append_chr(json, '\n');
+ monitor_puts(mon, qstring_get_str(json));
QDECREF(json);
}
assert(event < QEVENT_MAX);
switch (event) {
- case QEVENT_DEBUG:
- event_name = "DEBUG";
- break;
case QEVENT_SHUTDOWN:
event_name = "SHUTDOWN";
break;
case QEVENT_BLOCK_IO_ERROR:
event_name = "BLOCK_IO_ERROR";
break;
+ case QEVENT_RTC_CHANGE:
+ event_name = "RTC_CHANGE";
+ break;
+ case QEVENT_WATCHDOG:
+ event_name = "WATCHDOG";
+ break;
default:
abort();
break;
}
}
-static void do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
+static int do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const mon_cmd_t *cmd;
const char *item = qdict_get_try_str(qdict, "item");
if (cmd->name == NULL) {
if (monitor_ctrl_mode(mon)) {
- qemu_error_new(QERR_COMMAND_NOT_FOUND, item);
- return;
+ qerror_report(QERR_COMMAND_NOT_FOUND, item);
+ return -1;
}
goto help;
}
} else {
if (monitor_ctrl_mode(mon)) {
/* handler not converted yet */
- qemu_error_new(QERR_COMMAND_NOT_FOUND, item);
+ qerror_report(QERR_COMMAND_NOT_FOUND, item);
+ return -1;
} else {
cmd->mhandler.info(mon);
}
}
- return;
+ return 0;
help:
help_cmd(mon, "info");
+ return 0;
}
static void do_info_version_print(Monitor *mon, const QObject *data)
{
int index = qdict_get_int(qdict, "index");
if (mon_set_cpu(index) < 0) {
- qemu_error_new(QERR_INVALID_PARAMETER, "index");
+ qerror_report(QERR_INVALID_PARAMETER, "index");
return -1;
}
return 0;
if (bdrv_is_inserted(bs)) {
if (!force) {
if (!bdrv_is_removable(bs)) {
- qemu_error_new(QERR_DEVICE_NOT_REMOVABLE,
+ qerror_report(QERR_DEVICE_NOT_REMOVABLE,
bdrv_get_device_name(bs));
return -1;
}
if (bdrv_is_locked(bs)) {
- qemu_error_new(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
+ qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
return -1;
}
}
bs = bdrv_find(filename);
if (!bs) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, filename);
+ qerror_report(QERR_DEVICE_NOT_FOUND, filename);
return -1;
}
return eject_device(mon, bs, force);
bs = bdrv_find(qdict_get_str(qdict, "device"));
if (!bs) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
+ qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
return -1;
}
if (bdrv_set_key(bs, qdict_get_str(qdict, "password")) < 0) {
- qemu_error_new(QERR_INVALID_PASSWORD);
+ qerror_report(QERR_INVALID_PASSWORD);
return -1;
}
return 0;
}
-static void do_change_block(Monitor *mon, const char *device,
- const char *filename, const char *fmt)
+static int do_change_block(Monitor *mon, const char *device,
+ const char *filename, const char *fmt)
{
BlockDriverState *bs;
BlockDriver *drv = NULL;
bs = bdrv_find(device);
if (!bs) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, device);
- return;
+ qerror_report(QERR_DEVICE_NOT_FOUND, device);
+ return -1;
}
if (fmt) {
drv = bdrv_find_whitelisted_format(fmt);
if (!drv) {
- qemu_error_new(QERR_INVALID_BLOCK_FORMAT, fmt);
- return;
+ qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
+ return -1;
}
}
- if (eject_device(mon, bs, 0) < 0)
- return;
- bdrv_open2(bs, filename, BDRV_O_RDWR, drv);
- monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
+ if (eject_device(mon, bs, 0) < 0) {
+ return -1;
+ }
+ if (bdrv_open2(bs, filename, BDRV_O_RDWR, drv) < 0) {
+ return -1;
+ }
+ return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
}
-static void change_vnc_password(const char *password)
+static int change_vnc_password(const char *password)
{
- if (vnc_display_password(NULL, password) < 0)
- qemu_error_new(QERR_SET_PASSWD_FAILED);
+ if (vnc_display_password(NULL, password) < 0) {
+ qerror_report(QERR_SET_PASSWD_FAILED);
+ return -1;
+ }
+ return 0;
}
static void change_vnc_password_cb(Monitor *mon, const char *password,
monitor_read_command(mon, 1);
}
-static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
+static int do_change_vnc(Monitor *mon, const char *target, const char *arg)
{
if (strcmp(target, "passwd") == 0 ||
strcmp(target, "password") == 0) {
char password[9];
strncpy(password, arg, sizeof(password));
password[sizeof(password) - 1] = '\0';
- change_vnc_password(password);
+ return change_vnc_password(password);
} else {
- monitor_read_password(mon, change_vnc_password_cb, NULL);
+ return monitor_read_password(mon, change_vnc_password_cb, NULL);
}
} else {
- if (vnc_display_open(NULL, target) < 0)
- qemu_error_new(QERR_VNC_SERVER_FAILED, target);
+ if (vnc_display_open(NULL, target) < 0) {
+ qerror_report(QERR_VNC_SERVER_FAILED, target);
+ return -1;
+ }
}
+
+ return 0;
}
/**
* do_change(): Change a removable medium, or VNC configuration
*/
-static void do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
+static int do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *device = qdict_get_str(qdict, "device");
const char *target = qdict_get_str(qdict, "target");
const char *arg = qdict_get_try_str(qdict, "arg");
+ int ret;
+
if (strcmp(device, "vnc") == 0) {
- do_change_vnc(mon, target, arg);
+ ret = do_change_vnc(mon, target, arg);
} else {
- do_change_block(mon, device, target, arg);
+ ret = do_change_block(mon, device, target, arg);
}
+
+ return ret;
}
static void do_screen_dump(Monitor *mon, const QDict *qdict)
int flags;
flags = 0;
env = mon_get_cpu();
- if (!is_physical)
- return;
#ifdef TARGET_I386
if (wsize == 2) {
flags = 1;
f = fopen(filename, "wb");
if (!f) {
- qemu_error_new(QERR_OPEN_FILE_FAILED, filename);
+ qerror_report(QERR_OPEN_FILE_FAILED, filename);
return -1;
}
while (size != 0) {
f = fopen(filename, "wb");
if (!f) {
- qemu_error_new(QERR_OPEN_FILE_FAILED, filename);
+ qerror_report(QERR_OPEN_FILE_FAILED, filename);
return -1;
}
while (size != 0) {
int ret;
if (kvm_enabled() && !kvm_has_sync_mmu()) {
- qemu_error_new(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
+ qerror_report(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
return -1;
}
ret = qemu_balloon_status(cb, opaque);
if (!ret) {
- qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
+ qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
return -1;
}
int ret;
if (kvm_enabled() && !kvm_has_sync_mmu()) {
- qemu_error_new(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
+ qerror_report(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
return -1;
}
ret = qemu_balloon(qdict_get_int(params, "value"), cb, opaque);
if (ret == 0) {
- qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
+ qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
return -1;
}
+ cb(opaque, NULL);
return 0;
}
fd = qemu_chr_get_msgfd(mon->chr);
if (fd == -1) {
- qemu_error_new(QERR_FD_NOT_SUPPLIED);
+ qerror_report(QERR_FD_NOT_SUPPLIED);
return -1;
}
if (qemu_isdigit(fdname[0])) {
- qemu_error_new(QERR_INVALID_PARAMETER, "fdname");
+ qerror_report(QERR_INVALID_PARAMETER, "fdname");
return -1;
}
fd = dup(fd);
if (fd == -1) {
if (errno == EMFILE)
- qemu_error_new(QERR_TOO_MANY_FILES);
+ qerror_report(QERR_TOO_MANY_FILES);
else
- qemu_error_new(QERR_UNDEFINED_ERROR);
+ qerror_report(QERR_UNDEFINED_ERROR);
return -1;
}
return 0;
}
- qemu_error_new(QERR_FD_NOT_FOUND, fdname);
+ qerror_report(QERR_FD_NOT_FOUND, fdname);
return -1;
}
vm_stop(0);
- if (load_vmstate(mon, name) >= 0 && saved_vm_running)
+ if (load_vmstate(name) >= 0 && saved_vm_running)
vm_start();
}
return NULL;
}
-static void monitor_print_error(Monitor *mon)
+void monitor_set_error(Monitor *mon, QError *qerror)
{
- qerror_print(mon->error);
- QDECREF(mon->error);
- mon->error = NULL;
+ /* report only the first error */
+ if (!mon->error) {
+ mon->error = qerror;
+ } else {
+ MON_DEBUG("Additional error report at %s:%d\n",
+ qerror->file, qerror->linenr);
+ QDECREF(qerror);
+ }
}
static int is_async_return(const QObject *data)
return 0;
}
+static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret)
+{
+ if (monitor_ctrl_mode(mon)) {
+ if (ret && !monitor_has_error(mon)) {
+ /*
+ * If it returns failure, it must have passed on error.
+ *
+ * Action: Report an internal error to the client if in QMP.
+ */
+ qerror_report(QERR_UNDEFINED_ERROR);
+ MON_DEBUG("command '%s' returned failure but did not pass an error\n",
+ cmd->name);
+ }
+
+#ifdef CONFIG_DEBUG_MONITOR
+ if (!ret && monitor_has_error(mon)) {
+ /*
+ * If it returns success, it must not have passed an error.
+ *
+ * Action: Report the passed error to the client.
+ */
+ MON_DEBUG("command '%s' returned success but passed an error\n",
+ cmd->name);
+ }
+
+ if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) {
+ /*
+ * Handlers should not call Monitor print functions.
+ *
+ * Action: Ignore them in QMP.
+ *
+ * (XXX: we don't check any 'info' or 'query' command here
+ * because the user print function _is_ called by do_info(), hence
+ * we will trigger this check. This problem will go away when we
+ * make 'query' commands real and kill do_info())
+ */
+ MON_DEBUG("command '%s' called print functions %d time(s)\n",
+ cmd->name, mon_print_count_get(mon));
+ }
+#endif
+ } else {
+ assert(!monitor_has_error(mon));
+ QDECREF(mon->error);
+ mon->error = NULL;
+ }
+}
+
static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd,
const QDict *params)
{
+ int ret;
QObject *data = NULL;
- if (cmd->cmd_new_ret) {
- cmd->cmd_new_ret(mon, params, &data);
- } else {
- cmd->mhandler.cmd_new(mon, params, &data);
- }
+ mon_print_count_init(mon);
+
+ ret = cmd->mhandler.cmd_new(mon, params, &data);
+ handler_audit(mon, cmd, ret);
if (is_async_return(data)) {
/*
if (!cmd)
goto out;
- qemu_errors_to_mon(mon);
-
if (monitor_handler_is_async(cmd)) {
user_async_cmd_handler(mon, cmd, qdict);
} else if (monitor_handler_ported(cmd)) {
cmd->mhandler.cmd(mon, qdict);
}
- if (monitor_has_error(mon))
- monitor_print_error(mon);
-
- qemu_errors_to_previous();
-
out:
QDECREF(qdict);
}
static int check_opt(const CmdArgs *cmd_args, const char *name, QDict *args)
{
if (!cmd_args->optional) {
- qemu_error_new(QERR_MISSING_PARAMETER, name);
+ qerror_report(QERR_MISSING_PARAMETER, name);
return -1;
}
case 'B':
case 's':
if (qobject_type(value) != QTYPE_QSTRING) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "string");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "string");
return -1;
}
break;
for (i = 0; keys[i]; i++) {
QObject *obj = qdict_get(args, keys[i]);
if (!obj) {
- qemu_error_new(QERR_MISSING_PARAMETER, name);
+ qerror_report(QERR_MISSING_PARAMETER, name);
return -1;
}
if (qobject_type(obj) != QTYPE_QINT) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "int");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "int");
return -1;
}
}
case 'l':
case 'M':
if (qobject_type(value) != QTYPE_QINT) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "int");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "int");
return -1;
}
break;
case 'b':
case 'T':
if (qobject_type(value) != QTYPE_QINT && qobject_type(value) != QTYPE_QFLOAT) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "number");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "number");
return -1;
}
break;
case '-':
if (qobject_type(value) != QTYPE_QINT &&
qobject_type(value) != QTYPE_QBOOL) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "bool");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "bool");
return -1;
}
if (qobject_type(value) == QTYPE_QBOOL) {
const char *cmd_name, *info_item;
args = NULL;
- qemu_errors_to_mon(mon);
obj = json_parser_parse(tokens, NULL);
if (!obj) {
// FIXME: should be triggered in json_parser_parse()
- qemu_error_new(QERR_JSON_PARSING);
+ qerror_report(QERR_JSON_PARSING);
goto err_out;
} else if (qobject_type(obj) != QTYPE_QDICT) {
- qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "object");
+ qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "object");
qobject_decref(obj);
goto err_out;
}
obj = qdict_get(input, "execute");
if (!obj) {
- qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "execute");
+ qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute");
goto err_input;
} else if (qobject_type(obj) != QTYPE_QSTRING) {
- qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "string");
+ qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "string");
goto err_input;
}
cmd_name = qstring_get_str(qobject_to_qstring(obj));
if (invalid_qmp_mode(mon, cmd_name)) {
- qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
}
* converted into 'query-' commands
*/
if (compare_cmd(cmd_name, "info")) {
- qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
} else if (strstart(cmd_name, "query-", &info_item)) {
cmd = monitor_find_command("info");
} else {
cmd = monitor_find_command(cmd_name);
if (!cmd || !monitor_handler_ported(cmd)) {
- qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
}
}
monitor_protocol_emitter(mon, NULL);
out:
QDECREF(args);
- qemu_errors_to_previous();
}
/**
}
QLIST_INSERT_HEAD(&mon_list, mon, entry);
- if (!cur_mon || (flags & MONITOR_IS_DEFAULT))
- cur_mon = mon;
+ if (!default_mon || (flags & MONITOR_IS_DEFAULT))
+ default_mon = mon;
}
static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
monitor_read_command(mon, 1);
}
-void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
- BlockDriverCompletionFunc *completion_cb,
- void *opaque)
+int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
+ BlockDriverCompletionFunc *completion_cb,
+ void *opaque)
{
int err;
if (!bdrv_key_required(bs)) {
if (completion_cb)
completion_cb(opaque, 0);
- return;
+ return 0;
}
if (monitor_ctrl_mode(mon)) {
- qemu_error_new(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
- return;
+ qerror_report(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
+ return -1;
}
monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(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(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;
- }
-}
-
-void qemu_error_internal(const char *file, int linenr, const char *func,
- const char *fmt, ...)
-{
- va_list va;
- QError *qerror;
-
- assert(qemu_error_sink != NULL);
-
- va_start(va, fmt);
- qerror = qerror_from_info(file, linenr, func, fmt, &va);
- va_end(va);
-
- switch (qemu_error_sink->dest) {
- case ERR_SINK_FILE:
- qerror_print(qerror);
- QDECREF(qerror);
- break;
- case ERR_SINK_MONITOR:
- /* report only the first error */
- if (!qemu_error_sink->mon->error) {
- qemu_error_sink->mon->error = qerror;
- } else {
- /* XXX: warn the programmer */
- QDECREF(qerror);
- }
- break;
- }
+ return err;
}