* [Qemu-devel] [PATCH 1/9] Revert "char: use a fixed idx for child muxed chr"
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
@ 2016-10-13 11:14 ` Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 2/9] char: return a tag when adding the fe handlers Marc-André Lureau
` (9 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:14 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, berrange, imbrenda, Marc-André Lureau
That commit mis-used mux char: the frontend are multiplexed, not the
backend. Fix the regression preventing "c-a c" to switch the focus. The
following patches will fix the crash (when leaving or removing frontend)
by tracking frontends with handler tags.
This reverts commit 949055a2549afc4cde06b7972072c7288bb43722.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qemu-char.c | 22 +++++++---------------
include/sysemu/char.h | 1 -
2 files changed, 7 insertions(+), 16 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 721ce21..d83a896 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -165,7 +165,6 @@ CharDriverState *qemu_chr_alloc(ChardevCommon *backend, Error **errp)
CharDriverState *chr = g_malloc0(sizeof(CharDriverState));
qemu_mutex_init(&chr->chr_write_lock);
- chr->mux_idx = -1;
if (backend->has_logfile) {
int flags = O_WRONLY | O_CREAT;
if (backend->has_logappend &&
@@ -739,25 +738,17 @@ static void mux_chr_update_read_handler(CharDriverState *chr,
GMainContext *context)
{
MuxDriver *d = chr->opaque;
- int idx;
if (d->mux_cnt >= MAX_MUX) {
fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n");
return;
}
-
- if (chr->mux_idx == -1) {
- chr->mux_idx = d->mux_cnt++;
- }
-
- idx = chr->mux_idx;
- d->ext_opaque[idx] = chr->handler_opaque;
- d->chr_can_read[idx] = chr->chr_can_read;
- d->chr_read[idx] = chr->chr_read;
- d->chr_event[idx] = chr->chr_event;
-
+ d->ext_opaque[d->mux_cnt] = chr->handler_opaque;
+ d->chr_can_read[d->mux_cnt] = chr->chr_can_read;
+ d->chr_read[d->mux_cnt] = chr->chr_read;
+ d->chr_event[d->mux_cnt] = chr->chr_event;
/* Fix up the real driver with mux routines */
- if (d->mux_cnt == 1) {
+ if (d->mux_cnt == 0) {
qemu_chr_add_handlers_full(d->drv, mux_chr_can_read,
mux_chr_read,
mux_chr_event,
@@ -766,7 +757,8 @@ static void mux_chr_update_read_handler(CharDriverState *chr,
if (d->focus != -1) {
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
}
- d->focus = idx;
+ d->focus = d->mux_cnt;
+ d->mux_cnt++;
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
}
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 0d12175..19dad3f 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -107,7 +107,6 @@ struct CharDriverState {
int explicit_be_open;
int avail_connections;
int is_mux;
- int mux_idx;
guint fd_in_tag;
bool replay;
DECLARE_BITMAP(features, QEMU_CHAR_FEATURE_LAST);
--
2.10.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [Qemu-devel] [PATCH 2/9] char: return a tag when adding the fe handlers
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 1/9] Revert "char: use a fixed idx for child muxed chr" Marc-André Lureau
@ 2016-10-13 11:14 ` Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 3/9] char: add qemu_chr_remove_handlers() Marc-André Lureau
` (8 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:14 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, berrange, imbrenda, Marc-André Lureau
The tag helps to keep track of the frontend, and will be used in a later
change for removing the associated callbacks. Once the conversion is
done, a warning will be added to not ignore the return value, since that
would likely lead to an incorrect behaviour.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qemu-char.c | 149 ++++++++++++++++++++++++++++++++++----------------
include/sysemu/char.h | 13 ++++-
2 files changed, 111 insertions(+), 51 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index d83a896..168af69 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -89,6 +89,8 @@
#define READ_RETRIES 10
#define TCP_MAX_FDS 16
+typedef struct MuxDriver MuxDriver;
+
/***********************************************************/
/* Socket address helpers */
@@ -449,12 +451,14 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
static void remove_fd_in_watch(CharDriverState *chr);
-void qemu_chr_add_handlers_full(CharDriverState *s,
- IOCanReadHandler *fd_can_read,
- IOReadHandler *fd_read,
- IOEventHandler *fd_event,
- void *opaque,
- GMainContext *context)
+static void
+qemu_chr_set_handlers(CharDriverState *s,
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ void *opaque,
+ GMainContext *context,
+ int tag)
{
int fe_open;
@@ -469,7 +473,7 @@ void qemu_chr_add_handlers_full(CharDriverState *s,
s->chr_event = fd_event;
s->handler_opaque = opaque;
if (s->chr_update_read_handler) {
- s->chr_update_read_handler(s, context);
+ s->chr_update_read_handler(s, context, tag);
}
if (!s->explicit_fe_open) {
@@ -483,14 +487,43 @@ void qemu_chr_add_handlers_full(CharDriverState *s,
}
}
-void qemu_chr_add_handlers(CharDriverState *s,
- IOCanReadHandler *fd_can_read,
- IOReadHandler *fd_read,
- IOEventHandler *fd_event,
- void *opaque)
+static int mux_chr_new_handler_tag(CharDriverState *chr, GMainContext *context);
+static void mux_set_focus(MuxDriver *d, int focus);
+
+int qemu_chr_add_handlers_full(CharDriverState *s,
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ void *opaque,
+ GMainContext *context)
+{
+ int tag = 0;
+
+ if (s->is_mux) {
+ tag = mux_chr_new_handler_tag(s, context);
+ if (tag < 0) {
+ return tag;
+ }
+ }
+
+ qemu_chr_set_handlers(s, fd_can_read, fd_read,
+ fd_event, opaque, context, tag);
+
+ if (s->is_mux) {
+ mux_set_focus(s->opaque, tag);
+ }
+
+ return tag;
+}
+
+int qemu_chr_add_handlers(CharDriverState *s,
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ void *opaque)
{
- qemu_chr_add_handlers_full(s, fd_can_read, fd_read,
- fd_event, opaque, NULL);
+ return qemu_chr_add_handlers_full(s, fd_can_read, fd_read,
+ fd_event, opaque, NULL);
}
static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -519,7 +552,7 @@ static CharDriverState *qemu_chr_open_null(const char *id,
#define MAX_MUX 4
#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */
#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
-typedef struct {
+struct MuxDriver {
IOCanReadHandler *chr_can_read[MAX_MUX];
IOReadHandler *chr_read[MAX_MUX];
IOEventHandler *chr_event[MAX_MUX];
@@ -540,8 +573,7 @@ typedef struct {
/* Protected by the CharDriverState chr_write_lock. */
int linestart;
int64_t timestamps_start;
-} MuxDriver;
-
+};
/* Called with chr_write_lock held. */
static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -655,12 +687,9 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
qemu_chr_be_event(chr, CHR_EVENT_BREAK);
break;
case 'c':
+ assert(d->mux_cnt > 0); /* handler registered with first fe */
/* Switch to the next registered device */
- mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
- d->focus++;
- if (d->focus >= d->mux_cnt)
- d->focus = 0;
- mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
+ mux_set_focus(d, (d->focus + 1) % d->mux_cnt);
break;
case 't':
d->timestamps = !d->timestamps;
@@ -735,31 +764,18 @@ static void mux_chr_event(void *opaque, int event)
}
static void mux_chr_update_read_handler(CharDriverState *chr,
- GMainContext *context)
+ GMainContext *context,
+ int tag)
{
MuxDriver *d = chr->opaque;
- if (d->mux_cnt >= MAX_MUX) {
- fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n");
- return;
- }
- d->ext_opaque[d->mux_cnt] = chr->handler_opaque;
- d->chr_can_read[d->mux_cnt] = chr->chr_can_read;
- d->chr_read[d->mux_cnt] = chr->chr_read;
- d->chr_event[d->mux_cnt] = chr->chr_event;
- /* Fix up the real driver with mux routines */
- if (d->mux_cnt == 0) {
- qemu_chr_add_handlers_full(d->drv, mux_chr_can_read,
- mux_chr_read,
- mux_chr_event,
- chr, context);
- }
- if (d->focus != -1) {
- mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
- }
- d->focus = d->mux_cnt;
- d->mux_cnt++;
- mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
+ assert(tag >= 0);
+ assert(tag < d->mux_cnt);
+
+ d->ext_opaque[tag] = chr->handler_opaque;
+ d->chr_can_read[tag] = chr->chr_can_read;
+ d->chr_read[tag] = chr->chr_read;
+ d->chr_event[tag] = chr->chr_event;
}
static bool muxes_realized;
@@ -815,6 +831,39 @@ static void mux_chr_close(struct CharDriverState *chr)
g_free(d);
}
+static int mux_chr_new_handler_tag(CharDriverState *chr, GMainContext *context)
+{
+ MuxDriver *d = chr->opaque;
+
+ if (d->mux_cnt >= MAX_MUX) {
+ fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n");
+ return -1;
+ }
+
+ /* Fix up the real driver with mux routines */
+ if (d->mux_cnt == 0) {
+ qemu_chr_add_handlers_full(d->drv, mux_chr_can_read,
+ mux_chr_read,
+ mux_chr_event,
+ chr, context);
+ }
+
+ return d->mux_cnt++;
+}
+
+static void mux_set_focus(MuxDriver *d, int focus)
+{
+ assert(focus >= 0);
+ assert(focus < d->mux_cnt);
+
+ if (d->focus != -1) {
+ mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
+ }
+
+ d->focus = focus;
+ mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
+}
+
static CharDriverState *qemu_chr_open_mux(const char *id,
ChardevBackend *backend,
ChardevReturn *ret, Error **errp)
@@ -1085,7 +1134,8 @@ static GSource *fd_chr_add_watch(CharDriverState *chr, GIOCondition cond)
}
static void fd_chr_update_read_handler(CharDriverState *chr,
- GMainContext *context)
+ GMainContext *context,
+ int tag)
{
FDCharDriver *s = chr->opaque;
@@ -1342,7 +1392,8 @@ static void pty_chr_update_read_handler_locked(CharDriverState *chr)
}
static void pty_chr_update_read_handler(CharDriverState *chr,
- GMainContext *context)
+ GMainContext *context,
+ int tag)
{
qemu_mutex_lock(&chr->chr_write_lock);
pty_chr_update_read_handler_locked(chr);
@@ -2590,7 +2641,8 @@ static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
}
static void udp_chr_update_read_handler(CharDriverState *chr,
- GMainContext *context)
+ GMainContext *context,
+ int tag)
{
NetCharDriver *s = chr->opaque;
@@ -3009,7 +3061,8 @@ static void tcp_chr_connect(void *opaque)
}
static void tcp_chr_update_read_handler(CharDriverState *chr,
- GMainContext *context)
+ GMainContext *context,
+ int tag)
{
TCPCharDriver *s = chr->opaque;
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 19dad3f..bdd61ea 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -81,7 +81,7 @@ struct CharDriverState {
const uint8_t *buf, int len);
GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond);
void (*chr_update_read_handler)(struct CharDriverState *s,
- GMainContext *context);
+ GMainContext *context, int tag);
int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
int (*get_msgfds)(struct CharDriverState *s, int* fds, int num);
int (*set_msgfds)(struct CharDriverState *s, int *fds, int num);
@@ -432,14 +432,21 @@ void qemu_chr_be_write_impl(CharDriverState *s, uint8_t *buf, int len);
*/
void qemu_chr_be_event(CharDriverState *s, int event);
-void qemu_chr_add_handlers(CharDriverState *s,
+/**
+ * @qemu_chr_add_handlers:
+ *
+ * Register the frontend callbacks.
+ *
+ * Returns: a tag associated with the handlers, or -1 on error.
+ */
+int qemu_chr_add_handlers(CharDriverState *s,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
void *opaque);
/* This API can make handler run in the context what you pass to. */
-void qemu_chr_add_handlers_full(CharDriverState *s,
+int qemu_chr_add_handlers_full(CharDriverState *s,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
--
2.10.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [Qemu-devel] [PATCH 3/9] char: add qemu_chr_remove_handlers()
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 1/9] Revert "char: use a fixed idx for child muxed chr" Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 2/9] char: return a tag when adding the fe handlers Marc-André Lureau
@ 2016-10-13 11:14 ` Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 4/9] char: keep track of qemu_chr_add_handlers() Marc-André Lureau
` (7 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:14 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, berrange, imbrenda, Marc-André Lureau
Remove the handlers associated with a frontend tag.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qemu-char.c | 9 +++++++++
include/sysemu/char.h | 9 +++++++++
2 files changed, 18 insertions(+)
diff --git a/qemu-char.c b/qemu-char.c
index 168af69..a7fec6a 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -526,6 +526,15 @@ int qemu_chr_add_handlers(CharDriverState *s,
fd_event, opaque, NULL);
}
+void qemu_chr_remove_handlers(CharDriverState *s, int tag)
+{
+ if (tag < 0) {
+ return;
+ }
+ /* FIXME: recycle mux tag */
+ qemu_chr_set_handlers(s, NULL, NULL, NULL, NULL, NULL, tag);
+}
+
static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
return len;
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index bdd61ea..36d82b1 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -453,6 +453,15 @@ int qemu_chr_add_handlers_full(CharDriverState *s,
void *opaque,
GMainContext *context);
+/**
+ * @qemu_chr_remove_handlers:
+ *
+ * @tag: the tag returned from qemu_chr_add_handlers()
+ *
+ * Remove the frontend callbacks.
+ */
+void qemu_chr_remove_handlers(CharDriverState *s, int tag);
+
void qemu_chr_be_generic_open(CharDriverState *s);
void qemu_chr_accept_input(CharDriverState *s);
int qemu_chr_add_client(CharDriverState *s, int fd);
--
2.10.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [Qemu-devel] [PATCH 4/9] char: keep track of qemu_chr_add_handlers()
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
` (2 preceding siblings ...)
2016-10-13 11:14 ` [Qemu-devel] [PATCH 3/9] char: add qemu_chr_remove_handlers() Marc-André Lureau
@ 2016-10-13 11:14 ` Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 5/9] char: warn on unused qemu_chr_add_handlers() result Marc-André Lureau
` (6 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:14 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, berrange, imbrenda, Marc-André Lureau
Frontends should use qemu_chr_add_handlers()/qemu_chr_remove_handlers()
with the appropriate tag. This prevents from growing the mux char
frontends. A following patch will add error handling (check tag return
value and add an Error argument).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
backends/rng-egd.c | 13 ++++++++++---
gdbstub.c | 12 +++++++++---
hw/arm/pxa2xx.c | 14 +++++++++++++-
hw/arm/strongarm.c | 19 ++++++++++++++++++-
hw/char/bcm2835_aux.c | 13 ++++++++++++-
hw/char/cadence_uart.c | 16 +++++++++++++++-
hw/char/debugcon.c | 30 ++++++++++++++++--------------
hw/char/digic-uart.c | 13 ++++++++++++-
hw/char/escc.c | 17 ++++++++++++++++-
hw/char/etraxfs_ser.c | 14 +++++++++++++-
hw/char/exynos4210_uart.c | 12 +++++++++++-
hw/char/grlib_apbuart.c | 14 +++++++++++++-
hw/char/imx_serial.c | 15 +++++++++++++--
hw/char/ipoctal232.c | 18 +++++++++++++++++-
hw/char/lm32_juart.c | 14 +++++++++++++-
hw/char/lm32_uart.c | 14 +++++++++++++-
hw/char/mcf_uart.c | 4 +++-
hw/char/milkymist-uart.c | 14 +++++++++++++-
hw/char/pl011.c | 14 +++++++++++++-
hw/char/sclpconsole-lm.c | 11 ++++++++++-
hw/char/sclpconsole.c | 9 ++++++++-
hw/char/serial.c | 10 +++++++---
hw/char/sh_serial.c | 8 ++++++--
hw/char/spapr_vty.c | 14 +++++++++++++-
hw/char/stm32f2xx_usart.c | 13 ++++++++++++-
hw/char/virtio-console.c | 10 ++++++++--
hw/char/xen_console.c | 8 +++++---
hw/char/xilinx_uartlite.c | 17 +++++++++++++++--
hw/ipmi/ipmi_bmc_extern.c | 14 +++++++++++++-
hw/misc/ivshmem.c | 12 ++++++++++--
hw/usb/ccid-card-passthru.c | 9 ++++++++-
hw/usb/dev-serial.c | 16 ++++++++++++++--
hw/usb/redirect.c | 13 ++++++++++++-
monitor.c | 13 ++++++++-----
net/colo-compare.c | 22 ++++++++++++++--------
net/filter-mirror.c | 14 ++++++++++----
net/slirp.c | 6 ++++--
net/vhost-user.c | 8 +++++---
qemu-char.c | 6 ++++--
qtest.c | 4 +++-
tests/vhost-user-test.c | 7 +++++--
include/hw/char/bcm2835_aux.h | 1 +
include/hw/char/cadence_uart.h | 1 +
include/hw/char/digic-uart.h | 1 +
include/hw/char/imx_serial.h | 1 +
include/hw/char/serial.h | 1 +
include/hw/char/stm32f2xx_usart.h | 1 +
47 files changed, 443 insertions(+), 87 deletions(-)
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index ba17c07..5d8485f 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -25,6 +25,7 @@ typedef struct RngEgd
RngBackend parent;
CharDriverState *chr;
+ int chr_tag;
char *chr_name;
} RngEgd;
@@ -107,8 +108,11 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
}
/* FIXME we should resubmit pending requests when the CDS reconnects. */
- qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
- NULL, s);
+ if (s->chr_tag == -1) {
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read,
+ rng_egd_chr_read, NULL, s);
+ }
}
static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
@@ -137,6 +141,9 @@ static char *rng_egd_get_chardev(Object *obj, Error **errp)
static void rng_egd_init(Object *obj)
{
+ RngEgd *s = RNG_EGD(obj);
+
+ s->chr_tag = -1;
object_property_add_str(obj, "chardev",
rng_egd_get_chardev, rng_egd_set_chardev,
NULL);
@@ -147,7 +154,7 @@ static void rng_egd_finalize(Object *obj)
RngEgd *s = RNG_EGD(obj);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
qemu_chr_fe_release(s->chr);
}
diff --git a/gdbstub.c b/gdbstub.c
index ecea8c4..054a1d3 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -304,6 +304,7 @@ typedef struct GDBState {
int running_state;
#else
CharDriverState *chr;
+ int chr_tag;
CharDriverState *mon_chr;
#endif
char syscall_buf[256];
@@ -1724,6 +1725,7 @@ int gdbserver_start(const char *device)
GDBState *s;
char gdbstub_device_name[128];
CharDriverState *chr = NULL;
+ int chr_tag = -1;
CharDriverState *mon_chr;
ChardevCommon common = { 0 };
@@ -1750,8 +1752,9 @@ int gdbserver_start(const char *device)
return -1;
qemu_chr_fe_claim_no_fail(chr);
- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
- gdb_chr_event, NULL);
+ chr_tag =
+ qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
+ gdb_chr_event, NULL);
}
s = gdbserver_state;
@@ -1766,14 +1769,17 @@ int gdbserver_start(const char *device)
mon_chr->chr_write = gdb_monitor_write;
monitor_init(mon_chr, 0);
} else {
- if (s->chr)
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
qemu_chr_delete(s->chr);
+ }
mon_chr = s->mon_chr;
memset(s, 0, sizeof(GDBState));
}
s->c_cpu = first_cpu;
s->g_cpu = first_cpu;
s->chr = chr;
+ s->chr_tag = chr_tag;
s->state = chr ? RS_IDLE : RS_INACTIVE;
s->mon_chr = mon_chr;
s->current_syscall_cb = NULL;
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 0241e07..e17b904 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1765,6 +1765,7 @@ struct PXA2xxFIrState {
qemu_irq tx_dma;
uint32_t enable;
CharDriverState *chr;
+ int chr_tag;
uint8_t control[3];
uint8_t status[2];
@@ -1975,11 +1976,21 @@ static void pxa2xx_fir_realize(DeviceState *dev, Error **errp)
if (s->chr) {
qemu_chr_fe_claim_no_fail(s->chr);
- qemu_chr_add_handlers(s->chr, pxa2xx_fir_is_empty,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, pxa2xx_fir_is_empty,
pxa2xx_fir_rx, pxa2xx_fir_event, s);
}
}
+static void pxa2xx_fir_unrealize(DeviceState *dev, Error **errp)
+{
+ PXA2xxFIrState *s = PXA2XX_FIR(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static bool pxa2xx_fir_vmstate_validate(void *opaque, int version_id)
{
PXA2xxFIrState *s = opaque;
@@ -2013,6 +2024,7 @@ static void pxa2xx_fir_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = pxa2xx_fir_realize;
+ dc->unrealize = pxa2xx_fir_unrealize;
dc->vmsd = &pxa2xx_fir_vmsd;
dc->props = pxa2xx_fir_properties;
dc->reset = pxa2xx_fir_reset;
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 021cbf9..48b4a7c 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -913,6 +913,7 @@ typedef struct StrongARMUARTState {
MemoryRegion iomem;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint8_t utcr0;
@@ -1240,7 +1241,8 @@ static void strongarm_uart_init(Object *obj)
s->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_tx, s);
if (s->chr) {
- qemu_chr_add_handlers(s->chr,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr,
strongarm_uart_can_receive,
strongarm_uart_receive,
strongarm_uart_event,
@@ -1248,6 +1250,20 @@ static void strongarm_uart_init(Object *obj)
}
}
+static void strongarm_uart_finalize(Object *obj)
+{
+ StrongARMUARTState *s = STRONGARM_UART(obj);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+
+ timer_del(s->tx_timer);
+ timer_free(s->tx_timer);
+ timer_del(s->rx_timeout_timer);
+ timer_free(s->rx_timeout_timer);
+}
+
static void strongarm_uart_reset(DeviceState *dev)
{
StrongARMUARTState *s = STRONGARM_UART(dev);
@@ -1327,6 +1343,7 @@ static const TypeInfo strongarm_uart_info = {
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMUARTState),
.instance_init = strongarm_uart_init,
+ .instance_finalize = strongarm_uart_finalize,
.class_init = strongarm_uart_class_init,
};
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
index f7a845d..5694c32 100644
--- a/hw/char/bcm2835_aux.c
+++ b/hw/char/bcm2835_aux.c
@@ -283,11 +283,21 @@ static void bcm2835_aux_realize(DeviceState *dev, Error **errp)
BCM2835AuxState *s = BCM2835_AUX(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, bcm2835_aux_can_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, bcm2835_aux_can_receive,
bcm2835_aux_receive, NULL, s);
}
}
+static void bcm2835_aux_unrealize(DeviceState *dev, Error **errp)
+{
+ BCM2835AuxState *s = BCM2835_AUX(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static Property bcm2835_aux_props[] = {
DEFINE_PROP_CHR("chardev", BCM2835AuxState, chr),
DEFINE_PROP_END_OF_LIST(),
@@ -298,6 +308,7 @@ static void bcm2835_aux_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = bcm2835_aux_realize;
+ dc->unrealize = bcm2835_aux_unrealize;
dc->vmsd = &vmstate_bcm2835_aux;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->props = bcm2835_aux_props;
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index e3bc52f..7ca8f0a 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -475,11 +475,24 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
fifo_trigger_update, s);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
uart_event, s);
}
}
+static void cadence_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ CadenceUARTState *s = CADENCE_UART(dev);
+
+ timer_del(s->fifo_trigger_handle);
+ timer_free(s->fifo_trigger_handle);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void cadence_uart_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@@ -530,6 +543,7 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = cadence_uart_realize;
+ dc->unrealize = cadence_uart_unrealize;
dc->vmsd = &vmstate_cadence_uart;
dc->reset = cadence_uart_reset;
dc->props = cadence_uart_properties;
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index 4402033..45876a7 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -40,6 +40,7 @@
typedef struct DebugconState {
MemoryRegion io;
CharDriverState *chr;
+ int chr_tag;
uint32_t readback;
} DebugconState;
@@ -85,34 +86,34 @@ static const MemoryRegionOps debugcon_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static void debugcon_realize_core(DebugconState *s, Error **errp)
-{
- if (!s->chr) {
- error_setg(errp, "Can't create debugcon device, empty char device");
- return;
- }
-
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
-}
-
static void debugcon_isa_realizefn(DeviceState *dev, Error **errp)
{
ISADevice *d = ISA_DEVICE(dev);
ISADebugconState *isa = ISA_DEBUGCON_DEVICE(dev);
DebugconState *s = &isa->state;
- Error *err = NULL;
- debugcon_realize_core(s, &err);
- if (err != NULL) {
- error_propagate(errp, err);
+ if (!s->chr) {
+ error_setg(errp, "Can't create debugcon device, empty char device");
return;
}
+
+ /* necessary to start the be */
+ s->chr_tag = qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
+
memory_region_init_io(&s->io, OBJECT(dev), &debugcon_ops, s,
TYPE_ISA_DEBUGCON_DEVICE, 1);
memory_region_add_subregion(isa_address_space_io(d),
isa->iobase, &s->io);
}
+static void debugcon_isa_unrealizefn(DeviceState *dev, Error **errp)
+{
+ ISADebugconState *isa = ISA_DEBUGCON_DEVICE(dev);
+ DebugconState *s = &isa->state;
+
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+}
+
static Property debugcon_isa_properties[] = {
DEFINE_PROP_UINT32("iobase", ISADebugconState, iobase, 0xe9),
DEFINE_PROP_CHR("chardev", ISADebugconState, state.chr),
@@ -125,6 +126,7 @@ static void debugcon_isa_class_initfn(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = debugcon_isa_realizefn;
+ dc->unrealize = debugcon_isa_unrealizefn;
dc->props = debugcon_isa_properties;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c
index e96a9b2..83217a4 100644
--- a/hw/char/digic-uart.c
+++ b/hw/char/digic-uart.c
@@ -148,7 +148,17 @@ static void digic_uart_realize(DeviceState *dev, Error **errp)
DigicUartState *s = DIGIC_UART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ }
+}
+
+static void digic_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ DigicUartState *s = DIGIC_UART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
}
}
@@ -182,6 +192,7 @@ static void digic_uart_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = digic_uart_realize;
+ dc->unrealize = digic_uart_unrealize;
dc->reset = digic_uart_reset;
dc->vmsd = &vmstate_digic_uart;
dc->props = digic_uart_properties;
diff --git a/hw/char/escc.c b/hw/char/escc.c
index aa17397..0cbaf27 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -89,6 +89,7 @@ typedef struct ChannelState {
uint8_t wregs[SERIAL_REGS], rregs[SERIAL_REGS];
SERIOQueue queue;
CharDriverState *chr;
+ int chr_tag;
int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
int disabled;
int clock;
@@ -1015,7 +1016,8 @@ static void escc_realize(DeviceState *dev, Error **errp)
for (i = 0; i < 2; i++) {
if (s->chn[i].chr) {
s->chn[i].clock = s->frequency / 2;
- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+ s->chn[i].chr_tag =
+ qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event, &s->chn[i]);
}
}
@@ -1030,6 +1032,18 @@ static void escc_realize(DeviceState *dev, Error **errp)
}
}
+static void escc_unrealize(DeviceState *dev, Error **errp)
+{
+ ESCCState *s = ESCC(dev);
+ unsigned int i;
+
+ for (i = 0; i < 2; i++) {
+ if (s->chn[i].chr) {
+ qemu_chr_remove_handlers(s->chn[i].chr, s->chn[i].chr_tag);
+ }
+ }
+}
+
static Property escc_properties[] = {
DEFINE_PROP_UINT32("frequency", ESCCState, frequency, 0),
DEFINE_PROP_UINT32("it_shift", ESCCState, it_shift, 0),
@@ -1047,6 +1061,7 @@ static void escc_class_init(ObjectClass *klass, void *data)
dc->reset = escc_reset;
dc->realize = escc_realize;
+ dc->unrealize = escc_unrealize;
dc->vmsd = &vmstate_escc;
dc->props = escc_properties;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index c99cc5d..e606a76 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -54,6 +54,7 @@ typedef struct ETRAXSerial {
MemoryRegion mmio;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
int pending_tx;
@@ -232,12 +233,22 @@ static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
ETRAXSerial *s = ETRAX_SERIAL(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr,
serial_can_receive, serial_receive,
serial_event, s);
}
}
+static void etraxfs_ser_unrealize(DeviceState *dev, Error **errp)
+{
+ ETRAXSerial *s = ETRAX_SERIAL(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -245,6 +256,7 @@ static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
dc->reset = etraxfs_ser_reset;
dc->props = etraxfs_ser_properties;
dc->realize = etraxfs_ser_realize;
+ dc->unrealize = etraxfs_ser_unrealize;
}
static const TypeInfo etraxfs_ser_info = {
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index 1107578..ba84a4f 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -182,6 +182,7 @@ typedef struct Exynos4210UartState {
Exynos4210UartFIFO tx;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint32_t channel;
@@ -640,12 +641,20 @@ static int exynos4210_uart_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
- qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
exynos4210_uart_receive, exynos4210_uart_event, s);
return 0;
}
+static void exynos4210_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ Exynos4210UartState *s = EXYNOS4210_UART(dev);
+
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+}
+
static Property exynos4210_uart_properties[] = {
DEFINE_PROP_CHR("chardev", Exynos4210UartState, chr),
DEFINE_PROP_UINT32("channel", Exynos4210UartState, channel, 0),
@@ -663,6 +672,7 @@ static void exynos4210_uart_class_init(ObjectClass *klass, void *data)
dc->reset = exynos4210_uart_reset;
dc->props = exynos4210_uart_properties;
dc->vmsd = &vmstate_exynos4210_uart;
+ dc->unrealize = exynos4210_uart_unrealize;
}
static const TypeInfo exynos4210_uart_info = {
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index 778148a..963ca6d 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -79,6 +79,7 @@ typedef struct UART {
qemu_irq irq;
CharDriverState *chr;
+ int chr_tag;
/* registers */
uint32_t status;
@@ -242,7 +243,8 @@ static int grlib_apbuart_init(SysBusDevice *dev)
{
UART *uart = GRLIB_APB_UART(dev);
- qemu_chr_add_handlers(uart->chr,
+ uart->chr_tag =
+ qemu_chr_add_handlers(uart->chr,
grlib_apbuart_can_receive,
grlib_apbuart_receive,
grlib_apbuart_event,
@@ -271,6 +273,15 @@ static void grlib_apbuart_reset(DeviceState *d)
uart->current = 0;
}
+static void grlib_apbuart_unrealize(DeviceState *d, Error **errp)
+{
+ UART *uart = GRLIB_APB_UART(d);
+
+ if (uart->chr) {
+ qemu_chr_remove_handlers(uart->chr, uart->chr_tag);
+ }
+}
+
static Property grlib_apbuart_properties[] = {
DEFINE_PROP_CHR("chrdev", UART, chr),
DEFINE_PROP_END_OF_LIST(),
@@ -284,6 +295,7 @@ static void grlib_apbuart_class_init(ObjectClass *klass, void *data)
k->init = grlib_apbuart_init;
dc->reset = grlib_apbuart_reset;
dc->props = grlib_apbuart_properties;
+ dc->unrealize = grlib_apbuart_unrealize;
}
static const TypeInfo grlib_apbuart_info = {
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 5c3fa61..5ac3122 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -319,13 +319,23 @@ static void imx_serial_realize(DeviceState *dev, Error **errp)
IMXSerialState *s = IMX_SERIAL(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
- imx_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
+ imx_event, s);
} else {
DPRINTF("No char dev for uart\n");
}
}
+static void imx_serial_unrealize(DeviceState *dev, Error **errp)
+{
+ IMXSerialState *s = IMX_SERIAL(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void imx_serial_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@@ -347,6 +357,7 @@ static void imx_serial_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = imx_serial_realize;
+ dc->unrealize = imx_serial_unrealize;
dc->vmsd = &vmstate_imx_serial;
dc->reset = imx_serial_reset_at_boot;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index 2859fdd..4adc500 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -94,6 +94,7 @@ typedef struct SCC2698Block SCC2698Block;
struct SCC2698Channel {
IPOctalState *ipoctal;
CharDriverState *dev;
+ int chr_tag;
bool rx_enabled;
uint8_t mr[2];
uint8_t mr_idx;
@@ -547,7 +548,7 @@ static void ipoctal_realize(DeviceState *dev, Error **errp)
/* Redirect IP-Octal channels to host character devices */
if (ch->dev) {
- qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
+ ch->chr_tag = qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
hostdev_receive, hostdev_event, ch);
DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
} else {
@@ -556,6 +557,20 @@ static void ipoctal_realize(DeviceState *dev, Error **errp)
}
}
+static void ipoctal_unrealize(DeviceState *dev, Error **errp)
+{
+ IPOctalState *s = IPOCTAL(dev);
+ unsigned i;
+
+ for (i = 0; i < N_CHANNELS; i++) {
+ SCC2698Channel *ch = &s->ch[i];
+
+ if (ch->dev) {
+ qemu_chr_remove_handlers(ch->dev, ch->chr_tag);
+ }
+ }
+}
+
static Property ipoctal_properties[] = {
DEFINE_PROP_CHR("chardev0", IPOctalState, ch[0].dev),
DEFINE_PROP_CHR("chardev1", IPOctalState, ch[1].dev),
@@ -574,6 +589,7 @@ static void ipoctal_class_init(ObjectClass *klass, void *data)
IPackDeviceClass *ic = IPACK_DEVICE_CLASS(klass);
ic->realize = ipoctal_realize;
+ ic->unrealize = ipoctal_unrealize;
ic->io_read = io_read;
ic->io_write = io_write;
ic->id_read = id_read;
diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
index cb1ac76..065195d 100644
--- a/hw/char/lm32_juart.c
+++ b/hw/char/lm32_juart.c
@@ -45,6 +45,7 @@ struct LM32JuartState {
SysBusDevice parent_obj;
CharDriverState *chr;
+ int chr_tag;
uint32_t jtx;
uint32_t jrx;
@@ -121,7 +122,17 @@ static void lm32_juart_realize(DeviceState *dev, Error **errp)
LM32JuartState *s = LM32_JUART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
+ s->chr_tag = qemu_chr_add_handlers(s->chr, juart_can_rx,
+ juart_rx, juart_event, s);
+ }
+}
+
+static void lm32_juart_unrealize(DeviceState *dev, Error **errp)
+{
+ LM32JuartState *s = LM32_JUART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
}
}
@@ -149,6 +160,7 @@ static void lm32_juart_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_lm32_juart;
dc->props = lm32_juart_properties;
dc->realize = lm32_juart_realize;
+ dc->unrealize = lm32_juart_unrealize;
}
static const TypeInfo lm32_juart_info = {
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index be93697..c94cf19 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -98,6 +98,7 @@ struct LM32UartState {
MemoryRegion iomem;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint32_t regs[R_MAX];
@@ -268,7 +269,17 @@ static void lm32_uart_realize(DeviceState *dev, Error **errp)
LM32UartState *s = LM32_UART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ }
+}
+
+static void lm32_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ LM32UartState *s = LM32_UART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
}
}
@@ -295,6 +306,7 @@ static void lm32_uart_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_lm32_uart;
dc->props = lm32_uart_properties;
dc->realize = lm32_uart_realize;
+ dc->unrealize = lm32_uart_unrealize;
}
static const TypeInfo lm32_uart_info = {
diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c
index c184859..7a677c7 100644
--- a/hw/char/mcf_uart.c
+++ b/hw/char/mcf_uart.c
@@ -27,6 +27,7 @@ typedef struct {
int rx_enabled;
qemu_irq irq;
CharDriverState *chr;
+ int chr_tag;
} mcf_uart_state;
/* UART Status Register bits. */
@@ -284,7 +285,8 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
s->irq = irq;
if (chr) {
qemu_chr_fe_claim_no_fail(chr);
- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
mcf_uart_event, s);
}
mcf_uart_reset(s);
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index baddb37..0203512 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -62,6 +62,7 @@ struct MilkymistUartState {
MemoryRegion regs_region;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint32_t regs[R_MAX];
@@ -201,7 +202,17 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp)
MilkymistUartState *s = MILKYMIST_UART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ }
+}
+
+static void milkymist_uart_unrealize(DeviceState *dev, Error **errp)
+{
+ MilkymistUartState *s = MILKYMIST_UART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
}
}
@@ -237,6 +248,7 @@ static void milkymist_uart_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = milkymist_uart_realize;
+ dc->unrealize = milkymist_uart_unrealize;
dc->reset = milkymist_uart_reset;
dc->vmsd = &vmstate_milkymist_uart;
dc->props = milkymist_uart_properties;
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 786e605..903c044 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -36,6 +36,7 @@ typedef struct PL011State {
int read_count;
int read_trigger;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
const unsigned char *id;
} PL011State;
@@ -303,16 +304,27 @@ static void pl011_realize(DeviceState *dev, Error **errp)
PL011State *s = PL011(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
pl011_event, s);
}
}
+static void pl011_unrealize(DeviceState *dev, Error **errp)
+{
+ PL011State *s = PL011(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void pl011_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = pl011_realize;
+ dc->unrealize = pl011_unrealize;
dc->vmsd = &vmstate_pl011;
dc->props = pl011_properties;
}
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 9a56326..7c76d9e 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -38,6 +38,7 @@ typedef struct OprtnsCommand {
typedef struct SCLPConsoleLM {
SCLPEvent event;
CharDriverState *chr;
+ int chr_tag;
bool echo; /* immediate echo of input if true */
uint32_t write_errors; /* errors writing to char layer */
uint32_t length; /* length of byte stream in buffer */
@@ -313,7 +314,9 @@ static int console_init(SCLPEvent *event)
console_available = true;
if (scon->chr) {
- qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
+ scon->chr_tag =
+ qemu_chr_add_handlers(scon->chr, chr_can_read,
+ chr_read, NULL, scon);
}
return 0;
@@ -321,6 +324,12 @@ static int console_init(SCLPEvent *event)
static int console_exit(SCLPEvent *event)
{
+ SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
+
+ if (scon->chr) {
+ qemu_chr_remove_handlers(scon->chr, scon->chr_tag);
+ }
+
return 0;
}
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index a75ad4f..cf0b309 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -32,6 +32,7 @@ typedef struct ASCIIConsoleData {
typedef struct SCLPConsole {
SCLPEvent event;
CharDriverState *chr;
+ int chr_tag;
uint8_t iov[SIZE_BUFFER_VT220];
uint32_t iov_sclp; /* offset in buf for SCLP read operation */
uint32_t iov_bs; /* offset in buf for char layer read operation */
@@ -228,7 +229,8 @@ static int console_init(SCLPEvent *event)
}
console_available = true;
if (scon->chr) {
- qemu_chr_add_handlers(scon->chr, chr_can_read,
+ scon->chr_tag =
+ qemu_chr_add_handlers(scon->chr, chr_can_read,
chr_read, NULL, scon);
}
@@ -250,6 +252,11 @@ static void console_reset(DeviceState *dev)
static int console_exit(SCLPEvent *event)
{
+ SCLPConsole *scon = SCLP_CONSOLE(event);
+
+ if (scon->chr) {
+ qemu_chr_remove_handlers(scon->chr, scon->chr_tag);
+ }
return 0;
}
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 3442f47..9d7d57b 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -893,8 +893,9 @@ void serial_realize_core(SerialState *s, Error **errp)
s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s);
qemu_register_reset(serial_reset, s);
- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
- serial_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
+ serial_event, s);
fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
serial_reset(s);
@@ -902,7 +903,9 @@ void serial_realize_core(SerialState *s, Error **errp)
void serial_exit_core(SerialState *s)
{
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ s->chr_tag = -1;
+
qemu_unregister_reset(serial_reset, s);
}
@@ -933,6 +936,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
s->irq = irq;
s->baudbase = baudbase;
s->chr = chr;
+ s->chr_tag = -1;
serial_realize_core(s, &error_fatal);
vmstate_register(NULL, base, &vmstate_serial, s);
diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c
index 97ce562..e093689 100644
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -398,9 +398,13 @@ void sh_serial_init(MemoryRegion *sysmem,
s->chr = chr;
if (chr) {
+ int tag;
+
qemu_chr_fe_claim_no_fail(chr);
- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
- sh_serial_event, s);
+ tag = qemu_chr_add_handlers(chr, sh_serial_can_receive1,
+ sh_serial_receive1,
+ sh_serial_event, s);
+ assert(tag != -1);
}
s->eri = eri_source;
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index 9aeafc0..fdc32e3 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -12,6 +12,7 @@
typedef struct VIOsPAPRVTYDevice {
VIOsPAPRDevice sdev;
CharDriverState *chardev;
+ int chr_tag;
uint32_t in, out;
uint8_t buf[VTERM_BUFSIZE];
} VIOsPAPRVTYDevice;
@@ -74,10 +75,20 @@ static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
return;
}
- qemu_chr_add_handlers(dev->chardev, vty_can_receive,
+ dev->chr_tag =
+ qemu_chr_add_handlers(dev->chardev, vty_can_receive,
vty_receive, NULL, dev);
}
+static void spapr_vty_unrealize(DeviceState *s, Error **errp)
+{
+ VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(s);
+
+ if (dev->chardev) {
+ qemu_chr_remove_handlers(dev->chardev, dev->chr_tag);
+ }
+}
+
/* Forward declaration */
static target_ulong h_put_term_char(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
@@ -173,6 +184,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->props = spapr_vty_properties;
dc->vmsd = &vmstate_spapr_vty;
+ dc->unrealize = spapr_vty_unrealize;
}
static const TypeInfo spapr_vty_info = {
diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
index 4c6640d..9f8aac5 100644
--- a/hw/char/stm32f2xx_usart.c
+++ b/hw/char/stm32f2xx_usart.c
@@ -213,11 +213,21 @@ static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp)
STM32F2XXUsartState *s = STM32F2XX_USART(dev);
if (s->chr) {
- qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
stm32f2xx_usart_receive, NULL, s);
}
}
+static void stm32f2xx_usart_unrealize(DeviceState *dev, Error **errp)
+{
+ STM32F2XXUsartState *s = STM32F2XX_USART(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
+}
+
static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -225,6 +235,7 @@ static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
dc->reset = stm32f2xx_usart_reset;
dc->props = stm32f2xx_usart_properties;
dc->realize = stm32f2xx_usart_realize;
+ dc->unrealize = stm32f2xx_usart_unrealize;
}
static const TypeInfo stm32f2xx_usart_info = {
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index d44c18c..f3f3aa3 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -25,6 +25,7 @@ typedef struct VirtConsole {
VirtIOSerialPort parent_obj;
CharDriverState *chr;
+ int chr_tag;
guint watch;
} VirtConsole;
@@ -189,12 +190,14 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
*/
if (k->is_console) {
vcon->chr->explicit_fe_open = 0;
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
+ vcon->chr_tag =
+ qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
NULL, vcon);
virtio_serial_open(port);
} else {
vcon->chr->explicit_fe_open = 1;
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
+ vcon->chr_tag =
+ qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
chr_event, vcon);
}
}
@@ -207,6 +210,9 @@ static void virtconsole_unrealize(DeviceState *dev, Error **errp)
if (vcon->watch) {
g_source_remove(vcon->watch);
}
+ if (vcon->chr) {
+ qemu_chr_remove_handlers(vcon->chr, vcon->chr_tag);
+ }
}
static void virtconsole_class_init(ObjectClass *klass, void *data)
diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
index 83108b0..f263dfa 100644
--- a/hw/char/xen_console.c
+++ b/hw/char/xen_console.c
@@ -44,6 +44,7 @@ struct XenConsole {
int ring_ref;
void *sring;
CharDriverState *chr;
+ int chr_tag;
int backlog;
};
@@ -237,8 +238,9 @@ static int con_initialise(struct XenDevice *xendev)
xen_be_bind_evtchn(&con->xendev);
if (con->chr) {
if (qemu_chr_fe_claim(con->chr) == 0) {
- qemu_chr_add_handlers(con->chr, xencons_can_receive,
- xencons_receive, NULL, con);
+ con->chr_tag =
+ qemu_chr_add_handlers(con->chr, xencons_can_receive,
+ xencons_receive, NULL, con);
} else {
xen_be_printf(xendev, 0,
"xen_console_init error chardev %s already used\n",
@@ -260,7 +262,7 @@ static void con_disconnect(struct XenDevice *xendev)
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
if (con->chr) {
- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(con->chr, con->chr_tag);
qemu_chr_fe_release(con->chr);
}
xen_be_unbind_evtchn(&con->xendev);
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index 3766dc2..e6b103e 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -56,6 +56,7 @@ typedef struct XilinxUARTLite {
MemoryRegion mmio;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint8_t rx_fifo[8];
@@ -213,8 +214,19 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
{
XilinxUARTLite *s = XILINX_UARTLITE(dev);
- if (s->chr)
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ if (s->chr) {
+ s->chr_tag =
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ }
+}
+
+static void xilinx_uartlite_unrealize(DeviceState *dev, Error **errp)
+{
+ XilinxUARTLite *s = XILINX_UARTLITE(dev);
+
+ if (s->chr) {
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
+ }
}
static void xilinx_uartlite_init(Object *obj)
@@ -234,6 +246,7 @@ static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
dc->reset = xilinx_uartlite_reset;
dc->realize = xilinx_uartlite_realize;
+ dc->unrealize = xilinx_uartlite_unrealize;
dc->props = xilinx_uartlite_properties;
}
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index d93e3f3..927bed2 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -63,6 +63,7 @@ typedef struct IPMIBmcExtern {
IPMIBmc parent;
CharDriverState *chr;
+ int chr_tag;
bool connected;
@@ -447,7 +448,17 @@ static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp)
return;
}
- qemu_chr_add_handlers(ibe->chr, can_receive, receive, chr_event, ibe);
+ ibe->chr_tag =
+ qemu_chr_add_handlers(ibe->chr, can_receive, receive, chr_event, ibe);
+}
+
+static void ipmi_bmc_extern_unrealize(DeviceState *dev, Error **errp)
+{
+ IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(dev);
+
+ if (ibe->chr) {
+ qemu_chr_remove_handlers(ibe->chr, ibe->chr_tag);
+ }
}
static int ipmi_bmc_extern_post_migrate(void *opaque, int version_id)
@@ -512,6 +523,7 @@ static void ipmi_bmc_extern_class_init(ObjectClass *oc, void *data)
bk->handle_command = ipmi_bmc_extern_handle_command;
bk->handle_reset = ipmi_bmc_extern_handle_reset;
dc->realize = ipmi_bmc_extern_realize;
+ dc->unrealize = ipmi_bmc_extern_unrealize;
dc->props = ipmi_bmc_extern_properties;
}
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index f803dfd..19079f4 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -89,6 +89,7 @@ typedef struct IVShmemState {
/* exactly one of these two may be set */
HostMemoryBackend *hostmem; /* with interrupts */
CharDriverState *server_chr; /* without interrupts */
+ int server_chr_tag;
/* registers */
uint32_t intrmask;
@@ -841,6 +842,8 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
uint8_t attr = PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_PREFETCH;
+ s->server_chr_tag = -1;
+
/* IRQFD requires MSI */
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD) &&
!ivshmem_has_feature(s, IVSHMEM_MSI)) {
@@ -893,8 +896,9 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
return;
}
- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive,
- ivshmem_read, NULL, s);
+ s->server_chr_tag =
+ qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive,
+ ivshmem_read, NULL, s);
if (ivshmem_setup_interrupts(s) < 0) {
error_setg(errp, "failed to initialize interrupts");
@@ -955,6 +959,10 @@ static void ivshmem_exit(PCIDevice *dev)
}
g_free(s->msi_vectors);
+
+ if (s->server_chr) {
+ qemu_chr_remove_handlers(s->server_chr, s->server_chr_tag);
+ }
}
static int ivshmem_pre_load(void *opaque)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 2eacea7..8960972 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -49,6 +49,7 @@ typedef struct PassthruState PassthruState;
struct PassthruState {
CCIDCardState base;
CharDriverState *cs;
+ int chr_tag;
uint8_t vscard_in_data[VSCARD_IN_SIZE];
uint32_t vscard_in_pos;
uint32_t vscard_in_hdr;
@@ -347,7 +348,7 @@ static int passthru_initfn(CCIDCardState *base)
card->vscard_in_hdr = 0;
if (card->cs) {
DPRINTF(card, D_INFO, "initing chardev\n");
- qemu_chr_add_handlers(card->cs,
+ card->chr_tag = qemu_chr_add_handlers(card->cs,
ccid_card_vscard_can_read,
ccid_card_vscard_read,
ccid_card_vscard_event, card);
@@ -366,6 +367,12 @@ static int passthru_initfn(CCIDCardState *base)
static int passthru_exitfn(CCIDCardState *base)
{
+ PassthruState *card = PASSTHRU_CCID_CARD(base);
+
+ if (card->cs) {
+ qemu_chr_remove_handlers(card->cs, card->chr_tag);
+ }
+
return 0;
}
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 966ad84..4dcfc68 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -104,6 +104,7 @@ typedef struct {
QEMUSerialSetParams params;
int latency; /* ms */
CharDriverState *cs;
+ int chr_tag;
} USBSerialState;
#define TYPE_USB_SERIAL "usb-serial-dev"
@@ -499,8 +500,9 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
return;
}
- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
- usb_serial_event, s);
+ s->chr_tag =
+ qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
+ usb_serial_event, s);
usb_serial_handle_reset(dev);
if (s->cs->be_open && !dev->attached) {
@@ -508,6 +510,15 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
}
}
+static void usb_serial_unrealize(USBDevice *dev, Error **errp)
+{
+ USBSerialState *s = USB_SERIAL_DEV(dev);
+
+ if (s->cs) {
+ qemu_chr_remove_handlers(s->cs, s->chr_tag);
+ }
+}
+
static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
{
USBDevice *dev;
@@ -590,6 +601,7 @@ static void usb_serial_dev_class_init(ObjectClass *klass, void *data)
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
uc->realize = usb_serial_realize;
+ uc->unrealize = usb_serial_unrealize;
uc->handle_reset = usb_serial_handle_reset;
uc->handle_control = usb_serial_handle_control;
uc->handle_data = usb_serial_handle_data;
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index d4ca026..7d73c93 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -106,6 +106,7 @@ struct USBRedirDevice {
USBDevice dev;
/* Properties */
CharDriverState *cs;
+ int chr_tag;
uint8_t debug;
char *filter_str;
int32_t bootindex;
@@ -1375,6 +1376,7 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
USBRedirDevice *dev = USB_REDIRECT(udev);
int i;
+ dev->chr_tag = -1;
if (dev->cs == NULL) {
error_setg(errp, QERR_MISSING_PARAMETER, "chardev");
return;
@@ -1406,12 +1408,20 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH;
/* Let the backend know we are ready */
- qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
+ dev->chr_tag =
+ qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
usbredir_chardev_read, usbredir_chardev_event, dev);
qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
}
+static void usbredir_unrealize(USBDevice *udev, Error **errp)
+{
+ USBRedirDevice *dev = USB_REDIRECT(udev);
+
+ qemu_chr_remove_handlers(dev->cs, dev->chr_tag);
+}
+
static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
{
int i;
@@ -2493,6 +2503,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
uc->realize = usbredir_realize;
+ uc->unrealize = usbredir_unrealize;
uc->product_desc = "USB Redirection Device";
uc->handle_destroy = usbredir_handle_destroy;
uc->cancel_packet = usbredir_cancel_packet;
diff --git a/monitor.c b/monitor.c
index 8728dd9..0d6f0ad 100644
--- a/monitor.c
+++ b/monitor.c
@@ -187,6 +187,7 @@ typedef struct {
struct Monitor {
CharDriverState *chr;
+ int chr_tag;
int reset_seen;
int flags;
int suspend_cnt;
@@ -582,7 +583,7 @@ static void monitor_data_init(Monitor *mon)
static void monitor_data_destroy(Monitor *mon)
{
if (mon->chr) {
- qemu_chr_add_handlers(mon->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(mon->chr, mon->chr_tag);
}
if (monitor_is_qmp(mon)) {
json_message_parser_destroy(&mon->qmp.parser);
@@ -3988,13 +3989,15 @@ void monitor_init(CharDriverState *chr, int flags)
}
if (monitor_is_qmp(mon)) {
- qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read,
- monitor_qmp_event, mon);
+ mon->chr_tag =
+ qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read,
+ monitor_qmp_event, mon);
qemu_chr_fe_set_echo(chr, true);
json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
} else {
- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
- monitor_event, mon);
+ mon->chr_tag =
+ qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
+ monitor_event, mon);
}
qemu_mutex_lock(&monitor_lock);
diff --git a/net/colo-compare.c b/net/colo-compare.c
index 47703c5..88582c8 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -70,6 +70,8 @@ typedef struct CompareState {
char *outdev;
CharDriverState *chr_pri_in;
CharDriverState *chr_sec_in;
+ int chr_pri_tag;
+ int chr_sec_tag;
CharDriverState *chr_out;
SocketReadState pri_rs;
SocketReadState sec_rs;
@@ -451,7 +453,8 @@ static void compare_pri_chr_in(void *opaque, const uint8_t *buf, int size)
ret = net_fill_rstate(&s->pri_rs, buf, size);
if (ret == -1) {
- qemu_chr_add_handlers(s->chr_pri_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_pri_in, s->chr_pri_tag);
+ s->chr_pri_tag = -1;
error_report("colo-compare primary_in error");
}
}
@@ -467,7 +470,8 @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size)
ret = net_fill_rstate(&s->sec_rs, buf, size);
if (ret == -1) {
- qemu_chr_add_handlers(s->chr_sec_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_sec_in, s->chr_sec_tag);
+ s->chr_sec_tag = -1;
error_report("colo-compare secondary_in error");
}
}
@@ -480,10 +484,12 @@ static void *colo_compare_thread(void *opaque)
worker_context = g_main_context_new();
- qemu_chr_add_handlers_full(s->chr_pri_in, compare_chr_can_read,
- compare_pri_chr_in, NULL, s, worker_context);
- qemu_chr_add_handlers_full(s->chr_sec_in, compare_chr_can_read,
- compare_sec_chr_in, NULL, s, worker_context);
+ s->chr_pri_tag =
+ qemu_chr_add_handlers_full(s->chr_pri_in, compare_chr_can_read,
+ compare_pri_chr_in, NULL, s, worker_context);
+ s->chr_sec_tag =
+ qemu_chr_add_handlers_full(s->chr_sec_in, compare_chr_can_read,
+ compare_sec_chr_in, NULL, s, worker_context);
compare_loop = g_main_loop_new(worker_context, FALSE);
@@ -703,11 +709,11 @@ static void colo_compare_finalize(Object *obj)
CompareState *s = COLO_COMPARE(obj);
if (s->chr_pri_in) {
- qemu_chr_add_handlers(s->chr_pri_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_pri_in, s->chr_pri_tag);
qemu_chr_fe_release(s->chr_pri_in);
}
if (s->chr_sec_in) {
- qemu_chr_add_handlers(s->chr_sec_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_sec_in, s->chr_sec_tag);
qemu_chr_fe_release(s->chr_sec_in);
}
if (s->chr_out) {
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index 0ee58d9..8c1d613 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -39,6 +39,7 @@ typedef struct MirrorState {
char *indev;
char *outdev;
CharDriverState *chr_in;
+ int chr_in_tag;
CharDriverState *chr_out;
SocketReadState rs;
} MirrorState;
@@ -110,7 +111,8 @@ static void redirector_chr_read(void *opaque, const uint8_t *buf, int size)
ret = net_fill_rstate(&s->rs, buf, size);
if (ret == -1) {
- qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_in, s->chr_in_tag);
+ s->chr_in_tag = -1;
}
}
@@ -121,7 +123,8 @@ static void redirector_chr_event(void *opaque, int event)
switch (event) {
case CHR_EVENT_CLOSED:
- qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_in, s->chr_in_tag);
+ s->chr_in_tag = -1;
break;
default:
break;
@@ -185,7 +188,8 @@ static void filter_redirector_cleanup(NetFilterState *nf)
MirrorState *s = FILTER_REDIRECTOR(nf);
if (s->chr_in) {
- qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr_in, s->chr_in_tag);
+ s->chr_in_tag = -1;
qemu_chr_fe_release(s->chr_in);
}
if (s->chr_out) {
@@ -228,6 +232,7 @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
{
MirrorState *s = FILTER_REDIRECTOR(nf);
+ s->chr_in_tag = -1;
if (!s->indev && !s->outdev) {
error_setg(errp, "filter redirector needs 'indev' or "
"'outdev' at least one property set");
@@ -251,7 +256,8 @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
}
qemu_chr_fe_claim_no_fail(s->chr_in);
- qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
+ s->chr_in_tag =
+ qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
redirector_chr_read, redirector_chr_event, nf);
}
diff --git a/net/slirp.c b/net/slirp.c
index b60893f..80eefb0 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -683,6 +683,7 @@ int net_slirp_smb(const char *exported_dir)
struct GuestFwd {
CharDriverState *hd;
+ int chr_tag;
struct in_addr server;
int port;
Slirp *slirp;
@@ -765,8 +766,9 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
fwd->slirp = s->slirp;
qemu_chr_fe_claim_no_fail(fwd->hd);
- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
- NULL, fwd);
+ fwd->chr_tag =
+ qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
+ NULL, fwd);
}
return 0;
diff --git a/net/vhost-user.c b/net/vhost-user.c
index 5b94c84..f3cf623 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -21,6 +21,7 @@
typedef struct VhostUserState {
NetClientState nc;
CharDriverState *chr;
+ int chr_tag;
VHostNetState *vhost_net;
guint watch;
uint64_t acked_features;
@@ -151,7 +152,7 @@ static void vhost_user_cleanup(NetClientState *nc)
s->vhost_net = NULL;
}
if (s->chr) {
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+ qemu_chr_remove_handlers(s->chr, s->chr_tag);
qemu_chr_fe_release(s->chr);
s->chr = NULL;
}
@@ -258,14 +259,15 @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
}
s = DO_UPCAST(VhostUserState, nc, nc0);
+ s->chr_tag =
+ qemu_chr_add_handlers(chr, NULL, NULL,
+ net_vhost_user_event, nc0->name);
do {
Error *err = NULL;
if (qemu_chr_wait_connected(chr, &err) < 0) {
error_report_err(err);
return -1;
}
- qemu_chr_add_handlers(chr, NULL, NULL,
- net_vhost_user_event, nc0->name);
} while (!s->started);
assert(s->vhost_net);
diff --git a/qemu-char.c b/qemu-char.c
index a7fec6a..261a8f9 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -569,6 +569,7 @@ struct MuxDriver {
CharDriverState *drv;
int focus;
int mux_cnt;
+ int mux_tag;
int term_got_escape;
int max_size;
/* Intermediate input buffer allows to catch escape sequences even if the
@@ -850,8 +851,8 @@ static int mux_chr_new_handler_tag(CharDriverState *chr, GMainContext *context)
}
/* Fix up the real driver with mux routines */
- if (d->mux_cnt == 0) {
- qemu_chr_add_handlers_full(d->drv, mux_chr_can_read,
+ if (d->mux_tag == -1) {
+ d->mux_tag = qemu_chr_add_handlers_full(d->drv, mux_chr_can_read,
mux_chr_read,
mux_chr_event,
chr, context);
@@ -897,6 +898,7 @@ static CharDriverState *qemu_chr_open_mux(const char *id,
chr->opaque = d;
d->drv = drv;
d->focus = -1;
+ d->mux_tag = -1;
chr->chr_close = mux_chr_close;
chr->chr_write = mux_chr_write;
chr->chr_update_read_handler = mux_chr_update_read_handler;
diff --git a/qtest.c b/qtest.c
index 22482cc..73e07c2 100644
--- a/qtest.c
+++ b/qtest.c
@@ -39,6 +39,7 @@ bool qtest_allowed;
static DeviceState *irq_intercept_dev;
static FILE *qtest_log_fp;
static CharDriverState *qtest_chr;
+static int qtest_chr_tag;
static GString *inbuf;
static int irq_levels[MAX_IRQ];
static qemu_timeval start_time;
@@ -679,7 +680,8 @@ void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
qtest_log_fp = stderr;
}
- qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
+ qtest_chr_tag =
+ qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
qemu_chr_fe_set_echo(chr, true);
inbuf = g_string_new("");
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index d7c48c5..133cbdc 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -142,6 +142,7 @@ typedef struct TestServer {
gchar *mig_path;
gchar *chr_name;
CharDriverState *chr;
+ int chr_tag;
int fds_num;
int fds[VHOST_MEMORY_MAX_NREGIONS];
VhostUserMemory memory;
@@ -458,8 +459,9 @@ static void test_server_create_chr(TestServer *server, const gchar *opt)
server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
g_free(chr_path);
- qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
- chr_event, server);
+ server->chr_tag =
+ qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
+ chr_event, server);
}
static void test_server_listen(TestServer *server)
@@ -484,6 +486,7 @@ static gboolean _test_server_free(TestServer *server)
{
int i;
+ qemu_chr_remove_handlers(server->chr, server->chr_tag);
qemu_chr_delete(server->chr);
for (i = 0; i < server->fds_num; i++) {
diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h
index 42f0ee7..c55886e 100644
--- a/include/hw/char/bcm2835_aux.h
+++ b/include/hw/char/bcm2835_aux.h
@@ -23,6 +23,7 @@ typedef struct {
MemoryRegion iomem;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN];
diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h
index a12773c..e510d15 100644
--- a/include/hw/char/cadence_uart.h
+++ b/include/hw/char/cadence_uart.h
@@ -45,6 +45,7 @@ typedef struct {
uint32_t tx_count;
uint64_t char_tx_time;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
QEMUTimer *fifo_trigger_handle;
} CadenceUARTState;
diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h
index 7b3f145..160bf03 100644
--- a/include/hw/char/digic-uart.h
+++ b/include/hw/char/digic-uart.h
@@ -38,6 +38,7 @@ typedef struct DigicUartState {
MemoryRegion regs_region;
CharDriverState *chr;
+ int chr_tag;
uint32_t reg_rx;
uint32_t reg_st;
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
index 6cd75c0..cbf5859 100644
--- a/include/hw/char/imx_serial.h
+++ b/include/hw/char/imx_serial.h
@@ -97,6 +97,7 @@ typedef struct IMXSerialState {
qemu_irq irq;
CharDriverState *chr;
+ int chr_tag;
} IMXSerialState;
#endif
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index a4fd3d5..0ec91ea 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -53,6 +53,7 @@ struct SerialState {
int thr_ipending;
qemu_irq irq;
CharDriverState *chr;
+ int chr_tag;
int last_break_enable;
int it_shift;
int baudbase;
diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h
index b97f192..d9be1c0 100644
--- a/include/hw/char/stm32f2xx_usart.h
+++ b/include/hw/char/stm32f2xx_usart.h
@@ -68,6 +68,7 @@ typedef struct {
uint32_t usart_gtpr;
CharDriverState *chr;
+ int chr_tag;
qemu_irq irq;
} STM32F2XXUsartState;
#endif /* HW_STM32F2XX_USART_H */
--
2.10.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [Qemu-devel] [PATCH 5/9] char: warn on unused qemu_chr_add_handlers() result
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
` (3 preceding siblings ...)
2016-10-13 11:14 ` [Qemu-devel] [PATCH 4/9] char: keep track of qemu_chr_add_handlers() Marc-André Lureau
@ 2016-10-13 11:14 ` Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 6/9] qdev: remove call to qemu_chr_add_handlers() Marc-André Lureau
` (5 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:14 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, berrange, imbrenda, Marc-André Lureau
Enforce good usage of frontend handlers.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/sysemu/char.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 36d82b1..9632dbb 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -439,6 +439,7 @@ void qemu_chr_be_event(CharDriverState *s, int event);
*
* Returns: a tag associated with the handlers, or -1 on error.
*/
+G_GNUC_WARN_UNUSED_RESULT
int qemu_chr_add_handlers(CharDriverState *s,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
@@ -446,6 +447,7 @@ int qemu_chr_add_handlers(CharDriverState *s,
void *opaque);
/* This API can make handler run in the context what you pass to. */
+G_GNUC_WARN_UNUSED_RESULT
int qemu_chr_add_handlers_full(CharDriverState *s,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
--
2.10.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [Qemu-devel] [PATCH 6/9] qdev: remove call to qemu_chr_add_handlers()
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
` (4 preceding siblings ...)
2016-10-13 11:14 ` [Qemu-devel] [PATCH 5/9] char: warn on unused qemu_chr_add_handlers() result Marc-André Lureau
@ 2016-10-13 11:14 ` Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 7/9] char: handle qemu_chr_add_handlers() error Marc-André Lureau
` (4 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:14 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, berrange, imbrenda, Marc-André Lureau
chardev property is blindly trying to remove the frontend handlers, but
that doesn't work properly that way since there might be several
frontend on the same chardev. Instead, chardev frontend should use
qemu_chr_remove_handlers(). A previous commit should have fixed all
users.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/core/qdev-properties-system.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index e55afe6..73d4482 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -185,7 +185,6 @@ static void release_chr(Object *obj, const char *name, void *opaque)
CharDriverState *chr = *ptr;
if (chr) {
- qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(chr);
}
}
--
2.10.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [Qemu-devel] [PATCH 7/9] char: handle qemu_chr_add_handlers() error
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
` (5 preceding siblings ...)
2016-10-13 11:14 ` [Qemu-devel] [PATCH 6/9] qdev: remove call to qemu_chr_add_handlers() Marc-André Lureau
@ 2016-10-13 11:14 ` Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 8/9] ringbuf: fix chr_write return value Marc-André Lureau
` (3 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:14 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, berrange, imbrenda, Marc-André Lureau
Raise or assert on qemu_chr_add_handlers() error.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
backends/rng-egd.c | 2 +-
gdbstub.c | 4 ++--
hw/arm/pxa2xx.c | 3 ++-
hw/arm/strongarm.c | 3 ++-
hw/char/bcm2835_aux.c | 2 +-
hw/char/cadence_uart.c | 2 +-
hw/char/debugcon.c | 5 ++++-
hw/char/digic-uart.c | 3 ++-
hw/char/escc.c | 3 ++-
hw/char/etraxfs_ser.c | 4 ++--
hw/char/exynos4210_uart.c | 9 +++++++-
hw/char/grlib_apbuart.c | 3 ++-
hw/char/imx_serial.c | 2 +-
hw/char/ipoctal232.c | 5 ++++-
hw/char/lm32_juart.c | 3 ++-
hw/char/lm32_uart.c | 3 ++-
hw/char/mcf_uart.c | 3 ++-
hw/char/milkymist-uart.c | 3 ++-
hw/char/pl011.c | 2 +-
hw/char/sclpconsole-lm.c | 9 ++++++--
hw/char/sclpconsole.c | 3 ++-
hw/char/serial.c | 6 ++++-
hw/char/sh_serial.c | 3 ++-
hw/char/spapr_vty.c | 2 +-
hw/char/stm32f2xx_usart.c | 2 +-
hw/char/virtio-console.c | 7 ++++--
hw/char/xen_console.c | 11 +++++++++-
hw/char/xilinx_uartlite.c | 3 ++-
hw/ipmi/ipmi_bmc_extern.c | 3 ++-
hw/misc/ivshmem.c | 5 ++++-
hw/usb/ccid-card-passthru.c | 9 +++++++-
hw/usb/dev-serial.c | 6 ++++-
hw/usb/redirect.c | 6 ++++-
monitor.c | 12 +++++++---
net/colo-compare.c | 23 ++++++++++++++++----
net/filter-mirror.c | 6 ++++-
net/slirp.c | 8 ++++++-
net/vhost-user.c | 14 +++++++-----
qemu-char.c | 53 +++++++++++++++++++++++----------------------
qtest.c | 7 ++++--
stubs/monitor-init.c | 2 +-
tests/vhost-user-test.c | 3 ++-
vl.c | 2 +-
include/monitor/monitor.h | 2 +-
include/sysemu/char.h | 19 +++++-----------
45 files changed, 193 insertions(+), 97 deletions(-)
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index 5d8485f..a62eefa 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -111,7 +111,7 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
if (s->chr_tag == -1) {
s->chr_tag =
qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read,
- rng_egd_chr_read, NULL, s);
+ rng_egd_chr_read, NULL, s, NULL, errp);
}
}
diff --git a/gdbstub.c b/gdbstub.c
index 054a1d3..ee04be3 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1754,7 +1754,7 @@ int gdbserver_start(const char *device)
qemu_chr_fe_claim_no_fail(chr);
chr_tag =
qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
- gdb_chr_event, NULL);
+ gdb_chr_event, NULL, NULL, &error_abort);
}
s = gdbserver_state;
@@ -1767,7 +1767,7 @@ int gdbserver_start(const char *device)
/* Initialize a monitor terminal for gdb */
mon_chr = qemu_chr_alloc(&common, &error_abort);
mon_chr->chr_write = gdb_monitor_write;
- monitor_init(mon_chr, 0);
+ monitor_init(mon_chr, 0, &error_abort);
} else {
if (s->chr) {
qemu_chr_remove_handlers(s->chr, s->chr_tag);
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index e17b904..d70712d 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1978,7 +1978,8 @@ static void pxa2xx_fir_realize(DeviceState *dev, Error **errp)
qemu_chr_fe_claim_no_fail(s->chr);
s->chr_tag =
qemu_chr_add_handlers(s->chr, pxa2xx_fir_is_empty,
- pxa2xx_fir_rx, pxa2xx_fir_event, s);
+ pxa2xx_fir_rx, pxa2xx_fir_event,
+ s, NULL, errp);
}
}
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 48b4a7c..03150ab 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -39,6 +39,7 @@
#include "hw/ssi/ssi.h"
#include "qemu/cutils.h"
#include "qemu/log.h"
+#include "qapi/error.h"
//#define DEBUG
@@ -1246,7 +1247,7 @@ static void strongarm_uart_init(Object *obj)
strongarm_uart_can_receive,
strongarm_uart_receive,
strongarm_uart_event,
- s);
+ s, NULL, &error_abort);
}
}
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
index 5694c32..7e00c68 100644
--- a/hw/char/bcm2835_aux.c
+++ b/hw/char/bcm2835_aux.c
@@ -285,7 +285,7 @@ static void bcm2835_aux_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
qemu_chr_add_handlers(s->chr, bcm2835_aux_can_receive,
- bcm2835_aux_receive, NULL, s);
+ bcm2835_aux_receive, NULL, s, NULL, errp);
}
}
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 7ca8f0a..3d66e1b 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -477,7 +477,7 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
- uart_event, s);
+ uart_event, s, NULL, errp);
}
}
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index 45876a7..4f4e4e6 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -98,7 +98,10 @@ static void debugcon_isa_realizefn(DeviceState *dev, Error **errp)
}
/* necessary to start the be */
- s->chr_tag = qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
+ s->chr_tag = qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s, NULL, errp);
+ if (s->chr_tag == -1) {
+ return;
+ }
memory_region_init_io(&s->io, OBJECT(dev), &debugcon_ops, s,
TYPE_ISA_DEBUGCON_DEVICE, 1);
diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c
index 83217a4..04013f7 100644
--- a/hw/char/digic-uart.c
+++ b/hw/char/digic-uart.c
@@ -149,7 +149,8 @@ static void digic_uart_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event,
+ s, NULL, errp);
}
}
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 0cbaf27..0e97291 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -1018,7 +1018,8 @@ static void escc_realize(DeviceState *dev, Error **errp)
s->chn[i].clock = s->frequency / 2;
s->chn[i].chr_tag =
qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
- serial_receive1, serial_event, &s->chn[i]);
+ serial_receive1, serial_event, &s->chn[i],
+ NULL, errp);
}
}
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index e606a76..b7cf7b5 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -235,8 +235,8 @@ static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
qemu_chr_add_handlers(s->chr,
- serial_can_receive, serial_receive,
- serial_event, s);
+ serial_can_receive, serial_receive,
+ serial_event, s, NULL, errp);
}
}
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index ba84a4f..40139ae 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -24,6 +24,7 @@
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
#include "sysemu/char.h"
+#include "qapi/error.h"
#include "hw/arm/exynos4210.h"
@@ -633,6 +634,7 @@ DeviceState *exynos4210_uart_create(hwaddr addr,
static int exynos4210_uart_init(SysBusDevice *dev)
{
Exynos4210UartState *s = EXYNOS4210_UART(dev);
+ Error *err = NULL;
/* memory mapping */
memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_uart_ops, s,
@@ -643,7 +645,12 @@ static int exynos4210_uart_init(SysBusDevice *dev)
s->chr_tag =
qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
- exynos4210_uart_receive, exynos4210_uart_event, s);
+ exynos4210_uart_receive, exynos4210_uart_event,
+ s, NULL, &err);
+ if (err) {
+ error_report_err(err);
+ return -1;
+ }
return 0;
}
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index 963ca6d..dcacb3a 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -25,6 +25,7 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "sysemu/char.h"
+#include "qapi/error.h"
#include "trace.h"
@@ -248,7 +249,7 @@ static int grlib_apbuart_init(SysBusDevice *dev)
grlib_apbuart_can_receive,
grlib_apbuart_receive,
grlib_apbuart_event,
- uart);
+ uart, NULL, &error_abort);
sysbus_init_irq(dev, &uart->irq);
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 5ac3122..ceb9951 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -321,7 +321,7 @@ static void imx_serial_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
- imx_event, s);
+ imx_event, s, NULL, errp);
} else {
DPRINTF("No char dev for uart\n");
}
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index 4adc500..8175273 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -549,7 +549,10 @@ static void ipoctal_realize(DeviceState *dev, Error **errp)
/* Redirect IP-Octal channels to host character devices */
if (ch->dev) {
ch->chr_tag = qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
- hostdev_receive, hostdev_event, ch);
+ hostdev_receive, hostdev_event, ch, NULL, errp);
+ if (ch->chr_tag == -1) {
+ return;
+ }
DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
} else {
DPRINTF("Could not redirect channel %u, no chardev set\n", i);
diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
index 065195d..6c2677f 100644
--- a/hw/char/lm32_juart.c
+++ b/hw/char/lm32_juart.c
@@ -123,7 +123,8 @@ static void lm32_juart_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag = qemu_chr_add_handlers(s->chr, juart_can_rx,
- juart_rx, juart_event, s);
+ juart_rx, juart_event,
+ s, NULL, errp);
}
}
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index c94cf19..6c74c55 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -270,7 +270,8 @@ static void lm32_uart_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event,
+ s, NULL, errp);
}
}
diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c
index 7a677c7..3d9037d 100644
--- a/hw/char/mcf_uart.c
+++ b/hw/char/mcf_uart.c
@@ -10,6 +10,7 @@
#include "hw/m68k/mcf.h"
#include "sysemu/char.h"
#include "exec/address-spaces.h"
+#include "qapi/error.h"
typedef struct {
MemoryRegion iomem;
@@ -287,7 +288,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
qemu_chr_fe_claim_no_fail(chr);
s->chr_tag =
qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
- mcf_uart_event, s);
+ mcf_uart_event, s, NULL, &error_abort);
}
mcf_uart_reset(s);
return s;
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index 0203512..04fec4c 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -203,7 +203,8 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event,
+ s, NULL, errp);
}
}
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 903c044..0827c51 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -306,7 +306,7 @@ static void pl011_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
- pl011_event, s);
+ pl011_event, s, NULL, errp);
}
}
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 7c76d9e..5677864 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -18,6 +18,7 @@
#include "qemu/thread.h"
#include "qemu/error-report.h"
#include "sysemu/char.h"
+#include "qapi/error.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/event-facility.h"
@@ -304,8 +305,8 @@ static const VMStateDescription vmstate_sclplmconsole = {
static int console_init(SCLPEvent *event)
{
static bool console_available;
-
SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
+ Error *err = NULL;
if (console_available) {
error_report("Multiple line-mode operator consoles are not supported");
@@ -316,7 +317,11 @@ static int console_init(SCLPEvent *event)
if (scon->chr) {
scon->chr_tag =
qemu_chr_add_handlers(scon->chr, chr_can_read,
- chr_read, NULL, scon);
+ chr_read, NULL, scon, NULL, &err);
+ if (err) {
+ error_report_err(err);
+ return -1;
+ }
}
return 0;
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index cf0b309..d3f87ce 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -20,6 +20,7 @@
#include "hw/s390x/sclp.h"
#include "hw/s390x/event-facility.h"
#include "sysemu/char.h"
+#include "qapi/error.h"
typedef struct ASCIIConsoleData {
EventBufferHeader ebh;
@@ -231,7 +232,7 @@ static int console_init(SCLPEvent *event)
if (scon->chr) {
scon->chr_tag =
qemu_chr_add_handlers(scon->chr, chr_can_read,
- chr_read, NULL, scon);
+ chr_read, NULL, scon, NULL, &error_abort);
}
return 0;
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 9d7d57b..f877cec 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -895,7 +895,11 @@ void serial_realize_core(SerialState *s, Error **errp)
s->chr_tag =
qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
- serial_event, s);
+ serial_event, s, NULL, errp);
+ if (s->chr_tag == -1) {
+ return;
+ }
+
fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
serial_reset(s);
diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c
index e093689..034bc49 100644
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -29,6 +29,7 @@
#include "hw/sh4/sh.h"
#include "sysemu/char.h"
#include "exec/address-spaces.h"
+#include "qapi/error.h"
//#define DEBUG_SERIAL
@@ -403,7 +404,7 @@ void sh_serial_init(MemoryRegion *sysmem,
qemu_chr_fe_claim_no_fail(chr);
tag = qemu_chr_add_handlers(chr, sh_serial_can_receive1,
sh_serial_receive1,
- sh_serial_event, s);
+ sh_serial_event, s, NULL, &error_abort);
assert(tag != -1);
}
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index fdc32e3..dfb12ac 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -77,7 +77,7 @@ static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
dev->chr_tag =
qemu_chr_add_handlers(dev->chardev, vty_can_receive,
- vty_receive, NULL, dev);
+ vty_receive, NULL, dev, NULL, errp);
}
static void spapr_vty_unrealize(DeviceState *s, Error **errp)
diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
index 9f8aac5..b1897e9 100644
--- a/hw/char/stm32f2xx_usart.c
+++ b/hw/char/stm32f2xx_usart.c
@@ -215,7 +215,7 @@ static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
- stm32f2xx_usart_receive, NULL, s);
+ stm32f2xx_usart_receive, NULL, s, NULL, errp);
}
}
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index f3f3aa3..984dc25 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -192,13 +192,16 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
vcon->chr->explicit_fe_open = 0;
vcon->chr_tag =
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
- NULL, vcon);
+ NULL, vcon, NULL, errp);
+ if (vcon->chr_tag == -1) {
+ return;
+ }
virtio_serial_open(port);
} else {
vcon->chr->explicit_fe_open = 1;
vcon->chr_tag =
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
- chr_event, vcon);
+ chr_event, vcon, NULL, errp);
}
}
}
diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
index f263dfa..401ec8c 100644
--- a/hw/char/xen_console.c
+++ b/hw/char/xen_console.c
@@ -26,6 +26,7 @@
#include "hw/hw.h"
#include "sysemu/char.h"
#include "hw/xen/xen_backend.h"
+#include "qapi/error.h"
#include <xen/io/console.h>
@@ -200,6 +201,7 @@ static int con_init(struct XenDevice *xendev)
con->chr = serial_hds[con->xendev.dev];
} else {
snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
+ /* FIXME: leaks on destroy & initialize error */
con->chr = qemu_chr_new(label, output, NULL);
}
@@ -213,6 +215,7 @@ out:
static int con_initialise(struct XenDevice *xendev)
{
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
+ Error *err = NULL;
int limit;
if (xenstore_read_int(con->console, "ring-ref", &con->ring_ref) == -1)
@@ -240,7 +243,13 @@ static int con_initialise(struct XenDevice *xendev)
if (qemu_chr_fe_claim(con->chr) == 0) {
con->chr_tag =
qemu_chr_add_handlers(con->chr, xencons_can_receive,
- xencons_receive, NULL, con);
+ xencons_receive, NULL, con, NULL, &err);
+ if (con->chr_tag == -1) {
+ xen_be_printf(xendev, 0, "error: %s\n",
+ error_get_pretty(err));
+ error_free(err);
+ con->chr = NULL;
+ }
} else {
xen_be_printf(xendev, 0,
"xen_console_init error chardev %s already used\n",
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index e6b103e..664ac97 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -216,7 +216,8 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
if (s->chr) {
s->chr_tag =
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+ qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event,
+ s, NULL, errp);
}
}
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index 927bed2..e239834 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -449,7 +449,8 @@ static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp)
}
ibe->chr_tag =
- qemu_chr_add_handlers(ibe->chr, can_receive, receive, chr_event, ibe);
+ qemu_chr_add_handlers(ibe->chr, can_receive, receive,
+ chr_event, ibe, NULL, errp);
}
static void ipmi_bmc_extern_unrealize(DeviceState *dev, Error **errp)
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 19079f4..9983f7c 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -898,7 +898,10 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
s->server_chr_tag =
qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive,
- ivshmem_read, NULL, s);
+ ivshmem_read, NULL, s, NULL, errp);
+ if (s->server_chr_tag == -1) {
+ return;
+ }
if (ivshmem_setup_interrupts(s) < 0) {
error_setg(errp, "failed to initialize interrupts");
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 8960972..5c0870c 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -14,6 +14,7 @@
#include "qemu/sockets.h"
#include "ccid.h"
#include "cacard/vscard_common.h"
+#include "qapi/error.h"
#define DPRINTF(card, lvl, fmt, ...) \
do { \
@@ -343,6 +344,7 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
static int passthru_initfn(CCIDCardState *base)
{
PassthruState *card = PASSTHRU_CCID_CARD(base);
+ Error *err = NULL;
card->vscard_in_pos = 0;
card->vscard_in_hdr = 0;
@@ -351,7 +353,12 @@ static int passthru_initfn(CCIDCardState *base)
card->chr_tag = qemu_chr_add_handlers(card->cs,
ccid_card_vscard_can_read,
ccid_card_vscard_read,
- ccid_card_vscard_event, card);
+ ccid_card_vscard_event, card,
+ NULL, &err);
+ if (err) {
+ error_report_err(err);
+ return -1;
+ }
ccid_card_vscard_send_init(card);
} else {
error_report("missing chardev");
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 4dcfc68..a1e183a 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -502,7 +502,11 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
s->chr_tag =
qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
- usb_serial_event, s);
+ usb_serial_event, s, NULL, errp);
+ if (s->chr_tag == -1) {
+ return;
+ }
+
usb_serial_handle_reset(dev);
if (s->cs->be_open && !dev->attached) {
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 7d73c93..6dcc56b 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1410,7 +1410,11 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
/* Let the backend know we are ready */
dev->chr_tag =
qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
- usbredir_chardev_read, usbredir_chardev_event, dev);
+ usbredir_chardev_read, usbredir_chardev_event,
+ dev, NULL, errp);
+ if (dev->chr_tag == -1) {
+ return;
+ }
qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
}
diff --git a/monitor.c b/monitor.c
index 0d6f0ad..33e063e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3964,7 +3964,7 @@ static void __attribute__((constructor)) monitor_lock_init(void)
qemu_mutex_init(&monitor_lock);
}
-void monitor_init(CharDriverState *chr, int flags)
+void monitor_init(CharDriverState *chr, int flags, Error **errp)
{
static int is_first_init = 1;
Monitor *mon;
@@ -3991,13 +3991,19 @@ void monitor_init(CharDriverState *chr, int flags)
if (monitor_is_qmp(mon)) {
mon->chr_tag =
qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read,
- monitor_qmp_event, mon);
+ monitor_qmp_event, mon, NULL, errp);
qemu_chr_fe_set_echo(chr, true);
json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
} else {
mon->chr_tag =
qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
- monitor_event, mon);
+ monitor_event, mon, NULL, errp);
+ }
+
+ if (mon->chr_tag == -1) {
+ monitor_data_destroy(mon);
+ g_free(mon);
+ return;
}
qemu_mutex_lock(&monitor_lock);
diff --git a/net/colo-compare.c b/net/colo-compare.c
index 88582c8..58e894b 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -481,21 +481,36 @@ static void *colo_compare_thread(void *opaque)
GMainContext *worker_context;
GMainLoop *compare_loop;
CompareState *s = opaque;
+ Error *err = NULL;
worker_context = g_main_context_new();
s->chr_pri_tag =
- qemu_chr_add_handlers_full(s->chr_pri_in, compare_chr_can_read,
- compare_pri_chr_in, NULL, s, worker_context);
+ qemu_chr_add_handlers(s->chr_pri_in, compare_chr_can_read,
+ compare_pri_chr_in, NULL, s,
+ worker_context, &err);
+ if (err) {
+ goto end;
+ }
+
s->chr_sec_tag =
- qemu_chr_add_handlers_full(s->chr_sec_in, compare_chr_can_read,
- compare_sec_chr_in, NULL, s, worker_context);
+ qemu_chr_add_handlers(s->chr_sec_in, compare_chr_can_read,
+ compare_sec_chr_in, NULL, s,
+ worker_context, &err);
+ if (err) {
+ goto end;
+ }
compare_loop = g_main_loop_new(worker_context, FALSE);
g_main_loop_run(compare_loop);
g_main_loop_unref(compare_loop);
+
+end:
+ if (err) {
+ error_report_err(err);
+ }
g_main_context_unref(worker_context);
return NULL;
}
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index 8c1d613..13ea039 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -258,7 +258,11 @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
qemu_chr_fe_claim_no_fail(s->chr_in);
s->chr_in_tag =
qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
- redirector_chr_read, redirector_chr_event, nf);
+ redirector_chr_read, redirector_chr_event,
+ nf, NULL, errp);
+ if (s->chr_in_tag == -1) {
+ return;
+ }
}
if (s->outdev) {
diff --git a/net/slirp.c b/net/slirp.c
index 80eefb0..355c90c 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -40,6 +40,7 @@
#include "sysemu/char.h"
#include "sysemu/sysemu.h"
#include "qemu/cutils.h"
+#include "qapi/error.h"
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
{
@@ -704,6 +705,7 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
static int slirp_guestfwd(SlirpState *s, const char *config_str,
int legacy_format)
{
+ Error *err = NULL;
struct in_addr server = { .s_addr = 0 };
struct GuestFwd *fwd;
const char *p;
@@ -768,7 +770,11 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
qemu_chr_fe_claim_no_fail(fwd->hd);
fwd->chr_tag =
qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
- NULL, fwd);
+ NULL, fwd, NULL, &err);
+ if (fwd->chr_tag < 0) {
+ error_report_err(err);
+ return -1;
+ }
}
return 0;
diff --git a/net/vhost-user.c b/net/vhost-user.c
index f3cf623..804ccb7 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -234,7 +234,7 @@ static void net_vhost_user_event(void *opaque, int event)
static int net_vhost_user_init(NetClientState *peer, const char *device,
const char *name, CharDriverState *chr,
- int queues)
+ int queues, Error **errp)
{
NetClientState *nc, *nc0 = NULL;
VhostUserState *s;
@@ -261,11 +261,13 @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
s = DO_UPCAST(VhostUserState, nc, nc0);
s->chr_tag =
qemu_chr_add_handlers(chr, NULL, NULL,
- net_vhost_user_event, nc0->name);
+ net_vhost_user_event, nc0->name, NULL, errp);
+ if (s->chr_tag == -1) {
+ return -1;
+ }
+
do {
- Error *err = NULL;
- if (qemu_chr_wait_connected(chr, &err) < 0) {
- error_report_err(err);
+ if (qemu_chr_wait_connected(chr, errp) < 0) {
return -1;
}
} while (!s->started);
@@ -351,5 +353,5 @@ int net_init_vhost_user(const Netdev *netdev, const char *name,
return -1;
}
- return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
+ return net_vhost_user_init(peer, "vhost_user", name, chr, queues, errp);
}
diff --git a/qemu-char.c b/qemu-char.c
index 261a8f9..775015b 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -487,20 +487,22 @@ qemu_chr_set_handlers(CharDriverState *s,
}
}
-static int mux_chr_new_handler_tag(CharDriverState *chr, GMainContext *context);
+static int mux_chr_new_handler_tag(CharDriverState *chr, GMainContext *context,
+ Error **errp);
static void mux_set_focus(MuxDriver *d, int focus);
-int qemu_chr_add_handlers_full(CharDriverState *s,
- IOCanReadHandler *fd_can_read,
- IOReadHandler *fd_read,
- IOEventHandler *fd_event,
- void *opaque,
- GMainContext *context)
+int qemu_chr_add_handlers(CharDriverState *s,
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ void *opaque,
+ GMainContext *context,
+ Error **errp)
{
int tag = 0;
if (s->is_mux) {
- tag = mux_chr_new_handler_tag(s, context);
+ tag = mux_chr_new_handler_tag(s, context, errp);
if (tag < 0) {
return tag;
}
@@ -516,16 +518,6 @@ int qemu_chr_add_handlers_full(CharDriverState *s,
return tag;
}
-int qemu_chr_add_handlers(CharDriverState *s,
- IOCanReadHandler *fd_can_read,
- IOReadHandler *fd_read,
- IOEventHandler *fd_event,
- void *opaque)
-{
- return qemu_chr_add_handlers_full(s, fd_can_read, fd_read,
- fd_event, opaque, NULL);
-}
-
void qemu_chr_remove_handlers(CharDriverState *s, int tag)
{
if (tag < 0) {
@@ -841,21 +833,25 @@ static void mux_chr_close(struct CharDriverState *chr)
g_free(d);
}
-static int mux_chr_new_handler_tag(CharDriverState *chr, GMainContext *context)
+static int mux_chr_new_handler_tag(CharDriverState *chr, GMainContext *context,
+ Error **errp)
{
MuxDriver *d = chr->opaque;
if (d->mux_cnt >= MAX_MUX) {
- fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n");
+ error_setg(errp, "Cannot add I/O handlers, MUX array is full");
return -1;
}
/* Fix up the real driver with mux routines */
if (d->mux_tag == -1) {
- d->mux_tag = qemu_chr_add_handlers_full(d->drv, mux_chr_can_read,
- mux_chr_read,
- mux_chr_event,
- chr, context);
+ d->mux_tag = qemu_chr_add_handlers(d->drv, mux_chr_can_read,
+ mux_chr_read,
+ mux_chr_event,
+ chr, context, errp);
+ if (d->mux_tag == -1) {
+ return -1;
+ }
}
return d->mux_cnt++;
@@ -4090,11 +4086,16 @@ CharDriverState *qemu_chr_new_noreplay(const char *label, const char *filename,
chr = qemu_chr_new_from_opts(opts, init, &err);
if (err) {
- error_report_err(err);
+ goto end;
}
if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
qemu_chr_fe_claim_no_fail(chr);
- monitor_init(chr, MONITOR_USE_READLINE);
+ monitor_init(chr, MONITOR_USE_READLINE, &err);
+ }
+
+end:
+ if (err) {
+ error_report_err(err);
}
qemu_opts_del(opts);
return chr;
diff --git a/qtest.c b/qtest.c
index 73e07c2..e3a2a99 100644
--- a/qtest.c
+++ b/qtest.c
@@ -680,8 +680,11 @@ void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
qtest_log_fp = stderr;
}
- qtest_chr_tag =
- qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
+ qtest_chr_tag = qemu_chr_add_handlers(chr, qtest_can_read, qtest_read,
+ qtest_event, chr, NULL, errp);
+ if (qtest_chr_tag == -1) {
+ return;
+ }
qemu_chr_fe_set_echo(chr, true);
inbuf = g_string_new("");
diff --git a/stubs/monitor-init.c b/stubs/monitor-init.c
index de1bc7c..c24a76f 100644
--- a/stubs/monitor-init.c
+++ b/stubs/monitor-init.c
@@ -2,6 +2,6 @@
#include "qemu-common.h"
#include "monitor/monitor.h"
-void monitor_init(CharDriverState *chr, int flags)
+void monitor_init(CharDriverState *chr, int flags, Error **errp)
{
}
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 133cbdc..2e349a8 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -11,6 +11,7 @@
#include "qemu/osdep.h"
#include "libqtest.h"
+#include "qapi/error.h"
#include "qemu/option.h"
#include "qemu/range.h"
#include "qemu/sockets.h"
@@ -461,7 +462,7 @@ static void test_server_create_chr(TestServer *server, const gchar *opt)
server->chr_tag =
qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
- chr_event, server);
+ chr_event, server, NULL, &error_abort);
}
static void test_server_listen(TestServer *server)
diff --git a/vl.c b/vl.c
index c657acd..bab77e0 100644
--- a/vl.c
+++ b/vl.c
@@ -2418,7 +2418,7 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
}
qemu_chr_fe_claim_no_fail(chr);
- monitor_init(chr, flags);
+ monitor_init(chr, flags, errp);
return 0;
}
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index a714d8e..7d31d1b 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -16,7 +16,7 @@ extern Monitor *cur_mon;
bool monitor_cur_is_qmp(void);
-void monitor_init(CharDriverState *chr, int flags);
+void monitor_init(CharDriverState *chr, int flags, Error **errp);
void monitor_cleanup(void);
int monitor_suspend(Monitor *mon);
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 9632dbb..2c2083d 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -441,19 +441,12 @@ void qemu_chr_be_event(CharDriverState *s, int event);
*/
G_GNUC_WARN_UNUSED_RESULT
int qemu_chr_add_handlers(CharDriverState *s,
- IOCanReadHandler *fd_can_read,
- IOReadHandler *fd_read,
- IOEventHandler *fd_event,
- void *opaque);
-
-/* This API can make handler run in the context what you pass to. */
-G_GNUC_WARN_UNUSED_RESULT
-int qemu_chr_add_handlers_full(CharDriverState *s,
- IOCanReadHandler *fd_can_read,
- IOReadHandler *fd_read,
- IOEventHandler *fd_event,
- void *opaque,
- GMainContext *context);
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ void *opaque,
+ GMainContext *context,
+ Error **errp);
/**
* @qemu_chr_remove_handlers:
--
2.10.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [Qemu-devel] [PATCH 8/9] ringbuf: fix chr_write return value
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
` (6 preceding siblings ...)
2016-10-13 11:14 ` [Qemu-devel] [PATCH 7/9] char: handle qemu_chr_add_handlers() error Marc-André Lureau
@ 2016-10-13 11:14 ` Marc-André Lureau
2016-10-13 11:14 ` [Qemu-devel] [PATCH 9/9] tests: start chardev unit tests Marc-André Lureau
` (2 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:14 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, berrange, imbrenda, Marc-André Lureau
It should return the number of written bytes.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qemu-char.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qemu-char.c b/qemu-char.c
index 775015b..863e449 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3389,7 +3389,7 @@ static int ringbuf_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
}
}
- return 0;
+ return len;
}
static int ringbuf_chr_read(CharDriverState *chr, uint8_t *buf, int len)
--
2.10.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* [Qemu-devel] [PATCH 9/9] tests: start chardev unit tests
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
` (7 preceding siblings ...)
2016-10-13 11:14 ` [Qemu-devel] [PATCH 8/9] ringbuf: fix chr_write return value Marc-André Lureau
@ 2016-10-13 11:14 ` Marc-André Lureau
2016-10-13 11:36 ` [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Paolo Bonzini
2016-10-13 13:27 ` Peter Maydell
10 siblings, 0 replies; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:14 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, berrange, imbrenda, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/test-char.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++
tests/Makefile.include | 4 +
2 files changed, 242 insertions(+)
create mode 100644 tests/test-char.c
diff --git a/tests/test-char.c b/tests/test-char.c
new file mode 100644
index 0000000..fe1ccf2
--- /dev/null
+++ b/tests/test-char.c
@@ -0,0 +1,238 @@
+#include "qemu/osdep.h"
+
+#include "qemu-common.h"
+#include "qemu/config-file.h"
+#include "sysemu/char.h"
+#include "sysemu/sysemu.h"
+#include "qapi/error.h"
+#include "qmp-commands.h"
+
+typedef struct FeHandler {
+ char read_buf[128];
+ int read_count;
+ int last_event;
+} FeHandler;
+
+static int fe_can_read(void *opaque)
+{
+ FeHandler *h = opaque;
+
+ return sizeof(h->read_buf) - h->read_count;
+}
+
+static void fe_read(void *opaque, const uint8_t *buf, int size)
+{
+ FeHandler *h = opaque;
+
+ g_assert_cmpint(size, <=, fe_can_read(opaque));
+
+ memcpy(h->read_buf + h->read_count, buf, size);
+ h->read_count += size;
+}
+
+static void fe_event(void *opaque, int event)
+{
+ FeHandler *h = opaque;
+
+ h->last_event = event;
+}
+
+#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+static void char_stdio_test_subprocess(void)
+{
+ CharDriverState *chr;
+ int ret;
+
+ chr = qemu_chr_new("label", "stdio", NULL);
+ g_assert_nonnull(chr);
+
+ qemu_chr_fe_set_open(chr, true);
+ ret = qemu_chr_fe_write(chr, (void *)"buf", 4);
+ g_assert_cmpint(ret, ==, 4);
+
+ qemu_chr_delete(chr);
+}
+
+static void char_stdio_test(void)
+{
+ g_test_trap_subprocess("/char/stdio/subprocess", 0, 0);
+ g_test_trap_assert_passed();
+ g_test_trap_assert_stdout("buf");
+}
+#endif
+
+
+static void char_ringbuf_test(void)
+{
+ QemuOpts *opts;
+ CharDriverState *chr;
+ char *data;
+ int ret;
+
+ opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
+ 1, &error_abort);
+ qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+
+ qemu_opt_set(opts, "size", "5", &error_abort);
+ chr = qemu_chr_new_from_opts(opts, NULL, NULL);
+ g_assert_null(chr);
+ qemu_opts_del(opts);
+
+ opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
+ 1, &error_abort);
+ qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+ qemu_opt_set(opts, "size", "2", &error_abort);
+ chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
+ g_assert_nonnull(chr);
+ qemu_opts_del(opts);
+
+ ret = qemu_chr_fe_write(chr, (void *)"buff", 4);
+ g_assert_cmpint(ret, ==, 4);
+
+ data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
+ g_assert_cmpstr(data, ==, "ff");
+ g_free(data);
+
+ data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
+ g_assert_cmpstr(data, ==, "");
+ g_free(data);
+
+ qemu_chr_delete(chr);
+}
+
+static void char_mux_test(void)
+{
+ QemuOpts *opts;
+ CharDriverState *chr, *base;
+ char *data;
+ int tag1, tag2;
+ FeHandler h1 = { 0, }, h2 = { 0, };
+
+ opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
+ 1, &error_abort);
+ qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+ qemu_opt_set(opts, "size", "128", &error_abort);
+ qemu_opt_set(opts, "mux", "on", &error_abort);
+ chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
+ g_assert_nonnull(chr);
+ qemu_opts_del(opts);
+
+ tag1 = qemu_chr_add_handlers(chr,
+ fe_can_read,
+ fe_read,
+ fe_event,
+ &h1,
+ NULL,
+ &error_abort);
+ g_assert_cmpint(tag1, !=, -1);
+
+ tag2 = qemu_chr_add_handlers(chr,
+ fe_can_read,
+ fe_read,
+ fe_event,
+ &h2,
+ NULL,
+ &error_abort);
+ g_assert_cmpint(tag2, !=, -1);
+
+ g_assert_cmpint(qemu_chr_be_can_write(chr), !=, 0);
+
+ base = qemu_chr_find("mux-label-base");
+
+ /* the last handler has the focus */
+ qemu_chr_be_write(base, (void *)"hello", 6);
+ g_assert_cmpint(h1.read_count, ==, 0);
+ g_assert_cmpint(h2.read_count, ==, 6);
+ g_assert_cmpstr(h2.read_buf, ==, "hello");
+ h2.read_count = 0;
+
+ /* switch focus */
+ qemu_chr_be_write(base, (void *)"\1c", 2);
+
+ qemu_chr_be_write(base, (void *)"hello", 6);
+ g_assert_cmpint(h2.read_count, ==, 0);
+ g_assert_cmpint(h1.read_count, ==, 6);
+ g_assert_cmpstr(h1.read_buf, ==, "hello");
+ h1.read_count = 0;
+
+ /* remove first handler */
+ qemu_chr_remove_handlers(chr, tag1);
+ qemu_chr_be_write(base, (void *)"hello", 6);
+ g_assert_cmpint(h1.read_count, ==, 0);
+ g_assert_cmpint(h2.read_count, ==, 0);
+
+ qemu_chr_be_write(base, (void *)"\1c", 2);
+ qemu_chr_be_write(base, (void *)"hello", 6);
+ g_assert_cmpint(h1.read_count, ==, 0);
+ g_assert_cmpint(h2.read_count, ==, 6);
+ g_assert_cmpstr(h2.read_buf, ==, "hello");
+ h2.read_count = 0;
+
+ /* print help */
+ qemu_chr_be_write(base, (void *)"\1?", 2);
+ data = qmp_ringbuf_read("mux-label-base", 128, false, 0, &error_abort);
+ g_assert_cmpint(strlen(data), !=, 0);
+ g_free(data);
+
+ qemu_chr_remove_handlers(chr, tag1);
+ qemu_chr_remove_handlers(chr, tag2);
+ qemu_chr_delete(chr);
+}
+
+static void char_null_test(void)
+{
+ CharDriverState *chr;
+ int ret, tag;
+
+ chr = qemu_chr_find("label-null");
+ g_assert_null(chr);
+
+ chr = qemu_chr_new("label-null", "null", NULL);
+ chr = qemu_chr_find("label-null");
+ g_assert_nonnull(chr);
+
+ qemu_chr_fe_claim_no_fail(chr);
+ ret = qemu_chr_fe_claim(chr);
+ g_assert_cmpint(ret, ==, -1);
+
+ g_assert(qemu_chr_has_feature(chr,
+ QEMU_CHAR_FEATURE_FD_PASS) == false);
+ g_assert(qemu_chr_has_feature(chr,
+ QEMU_CHAR_FEATURE_RECONNECTABLE) == false);
+
+ qemu_chr_fe_set_open(chr, true);
+
+ tag = qemu_chr_add_handlers(chr,
+ fe_can_read,
+ fe_read,
+ fe_event,
+ NULL,
+ NULL,
+ &error_abort);
+ g_assert_cmpint(tag, !=, -1);
+
+ ret = qemu_chr_fe_write(chr, (void *)"buf", 4);
+ g_assert_cmpint(ret, ==, 4);
+
+ qemu_chr_remove_handlers(chr, tag);
+ qemu_chr_fe_release(chr);
+ qemu_chr_delete(chr);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+ qemu_add_opts(&qemu_chardev_opts);
+
+ g_test_add_func("/char/null", char_null_test);
+ g_test_add_func("/char/ringbuf", char_ringbuf_test);
+ g_test_add_func("/char/mux", char_mux_test);
+#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+ g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess);
+ g_test_add_func("/char/stdio", char_stdio_test);
+#endif
+
+ return g_test_run();
+}
diff --git a/tests/Makefile.include b/tests/Makefile.include
index a77777c..c42eca5 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -8,6 +8,8 @@ SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \
check-unit-y = tests/check-qdict$(EXESUF)
gcov-files-check-qdict-y = qobject/qdict.c
+check-unit-y = tests/test-char$(EXESUF)
+gcov-files-check-qdict-y = qemu-char.c
check-unit-y += tests/check-qfloat$(EXESUF)
gcov-files-check-qfloat-y = qobject/qfloat.c
check-unit-y += tests/check-qint$(EXESUF)
@@ -479,6 +481,8 @@ tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
+
+tests/test-char$(EXESUF): tests/test-char.o qemu-char.o qemu-timer.o $(test-util-obj-y) $(qtest-obj-y) $(test-io-obj-y)
tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
tests/test-rfifolock$(EXESUF): tests/test-rfifolock.o $(test-util-obj-y)
--
2.10.0
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2)
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
` (8 preceding siblings ...)
2016-10-13 11:14 ` [Qemu-devel] [PATCH 9/9] tests: start chardev unit tests Marc-André Lureau
@ 2016-10-13 11:36 ` Paolo Bonzini
2016-10-13 11:50 ` Marc-André Lureau
2016-10-13 13:27 ` Peter Maydell
10 siblings, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2016-10-13 11:36 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel; +Cc: berrange, imbrenda
On 13/10/2016 13:14, Marc-André Lureau wrote:
> Hi,
>
> Commit 949055a2 "char: use a fixed idx for child muxed chr" introduced
> a regression in mux usage, since it wrongly interpreted mux as muxing
> various chr backend. Instead, it muxes frontends.
>
> The first patch reverts the broken change, the following patches add
> tracking to frontend handler, finally the last patch adds some tests
> that would have helped to track the crash and the regression. There is
> also a small fix for ringbuf.
In general I like the solution, but I dislike the API.
Would it work if we had something like
struct CharBackend {
CharDriverState *chr;
int tag;
}
and we modified all qemu_chr_fe_* functions (plus
qemu_chr_add_handlers[1]) to take a struct CharBackend. chardev
properties would also take a struct CharBackend. Then removing handlers
can still be done in release_chr, making the patches much smaller.
The conversion is a bit tedious, but I think it's much easier compared
to patch 4. I feel bad for having you redo everything and in particular
patch 7, but this is the model that the block layer uses and it works
very well there.
[1] while at it, it's probably best to rename qemu_chr_add_handlers
to qemu_chr_fe_add_handlers as the first patch in the series,
so that qemu_chr_add_handlers(CharDriverState *chr, ..., int tag)
can take the role of qemu_chr_set_handlers in this series.
Thanks,
Paolo
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2)
2016-10-13 11:36 ` [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Paolo Bonzini
@ 2016-10-13 11:50 ` Marc-André Lureau
2016-10-13 11:58 ` Paolo Bonzini
0 siblings, 1 reply; 14+ messages in thread
From: Marc-André Lureau @ 2016-10-13 11:50 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Marc-André Lureau, qemu-devel, berrange, imbrenda
Hi
----- Original Message -----
>
>
> On 13/10/2016 13:14, Marc-André Lureau wrote:
> > Hi,
> >
> > Commit 949055a2 "char: use a fixed idx for child muxed chr" introduced
> > a regression in mux usage, since it wrongly interpreted mux as muxing
> > various chr backend. Instead, it muxes frontends.
> >
> > The first patch reverts the broken change, the following patches add
> > tracking to frontend handler, finally the last patch adds some tests
> > that would have helped to track the crash and the regression. There is
> > also a small fix for ringbuf.
>
> In general I like the solution, but I dislike the API.
>
> Would it work if we had something like
>
> struct CharBackend {
> CharDriverState *chr;
> int tag;
> }
>
You mean front-end right?
> and we modified all qemu_chr_fe_* functions (plus
> qemu_chr_add_handlers[1]) to take a struct CharBackend. chardev
> properties would also take a struct CharBackend. Then removing handlers
> can still be done in release_chr, making the patches much smaller.
As long as they use chardev property, it's not always the case.
> The conversion is a bit tedious, but I think it's much easier compared
Yes, it's tedious :) Do you mind if I try to make the change on top? If it really reduces the patch 4/7, we could try to squash it?
> to patch 4. I feel bad for having you redo everything and in particular
> patch 7, but this is the model that the block layer uses and it works
> very well there.
Which function btw?
>
> [1] while at it, it's probably best to rename qemu_chr_add_handlers
> to qemu_chr_fe_add_handlers as the first patch in the series,
> so that qemu_chr_add_handlers(CharDriverState *chr, ..., int tag)
> can take the role of qemu_chr_set_handlers in this series.
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2)
2016-10-13 11:50 ` Marc-André Lureau
@ 2016-10-13 11:58 ` Paolo Bonzini
0 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2016-10-13 11:58 UTC (permalink / raw)
To: Marc-André Lureau
Cc: Marc-André Lureau, qemu-devel, berrange, imbrenda
On 13/10/2016 13:50, Marc-André Lureau wrote:
> Hi
>
> ----- Original Message -----
>>
>>
>> On 13/10/2016 13:14, Marc-André Lureau wrote:
>>> Hi,
>>>
>>> Commit 949055a2 "char: use a fixed idx for child muxed chr" introduced
>>> a regression in mux usage, since it wrongly interpreted mux as muxing
>>> various chr backend. Instead, it muxes frontends.
>>>
>>> The first patch reverts the broken change, the following patches add
>>> tracking to frontend handler, finally the last patch adds some tests
>>> that would have helped to track the crash and the regression. There is
>>> also a small fix for ringbuf.
>>
>> In general I like the solution, but I dislike the API.
>>
>> Would it work if we had something like
>>
>> struct CharBackend {
>> CharDriverState *chr;
>> int tag;
>> }
>>
>
> You mean front-end right?
The front-end is in hw/char. The back-end as seen by the front-end is a
(chr, tag) pair---so that struct should be CharBackend. The actual
back-end is the CharDriverState, but the front-end doesn't know.
I guess you can keep the qemu_chr_fe_* naming convention, which is
confusing anyway...
>> and we modified all qemu_chr_fe_* functions (plus
>> qemu_chr_add_handlers[1]) to take a struct CharBackend. chardev
>> properties would also take a struct CharBackend. Then removing handlers
>> can still be done in release_chr, making the patches much smaller.
>
> As long as they use chardev property, it's not always the case.
>
>> The conversion is a bit tedious, but I think it's much easier compared
>
> Yes, it's tedious :) Do you mind if I try to make the change on top? If it really reduces the patch 4/7, we could try to squash it?
You can always start the development like that, I won't notice. If you
squash everything together and re-separate the patches from scratch at
the end, I won't notice either. :)
But note that for example you don't need to do all the new unrealize
stuff, so perhaps you can start by undoing that in patch 4.
>> to patch 4. I feel bad for having you redo everything and in particular
>> patch 7, but this is the model that the block layer uses and it works
>> very well there.
>
> Which function btw?
I'm thinking of the separation between BlockBackend and
BlockDriverState. BlockBackend started as a very thin veneer over
BlockDriverState, but we've moved functionality out of BDS slowly
whenever it made sense.
Paolo
>>
>> [1] while at it, it's probably best to rename qemu_chr_add_handlers
>> to qemu_chr_fe_add_handlers as the first patch in the series,
>> so that qemu_chr_add_handlers(CharDriverState *chr, ..., int tag)
>> can take the role of qemu_chr_set_handlers in this series.
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2)
2016-10-13 11:14 [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Marc-André Lureau
` (9 preceding siblings ...)
2016-10-13 11:36 ` [Qemu-devel] [PATCH 0/9] Fix mux regression (commit 949055a2) Paolo Bonzini
@ 2016-10-13 13:27 ` Peter Maydell
10 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2016-10-13 13:27 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: QEMU Developers, Paolo Bonzini, imbrenda
On 13 October 2016 at 12:14, Marc-André Lureau
<marcandre.lureau@redhat.com> wrote:
> Hi,
>
> Commit 949055a2 "char: use a fixed idx for child muxed chr" introduced
> a regression in mux usage, since it wrongly interpreted mux as muxing
> various chr backend. Instead, it muxes frontends.
>
> The first patch reverts the broken change, the following patches add
> tracking to frontend handler, finally the last patch adds some tests
> that would have helped to track the crash and the regression. There is
> also a small fix for ringbuf.
As discussed on IRC, I have applied patch 1/9 to master to fix
the regression for the moment.
thanks
-- PMM
^ permalink raw reply [flat|nested] 14+ messages in thread