chardev: fix mess in OPENED/CLOSED events when muxed

When chardev is multiplexed (mux=on) there are a lot of cases where
CHR_EVENT_OPENED/CHR_EVENT_CLOSED events pairing (expected from
frontend side) is broken. There are either generation of multiple
repeated or extra CHR_EVENT_OPENED events, or CHR_EVENT_CLOSED just
isn't generated at all.
This is mostly because 'qemu_chr_fe_set_handlers()' function makes its
own (and often wrong) implicit decision on updated frontend state and
invokes 'fd_event' callback with 'CHR_EVENT_OPENED'. And even worse,
it doesn't do symmetric action in opposite direction, as someone may
expect (i.e. it doesn't invoke previously set 'fd_event' with
'CHR_EVENT_CLOSED'). Muxed chardev uses trick by calling this function
again to replace callback handlers with its own ones, but it doesn't
account for such side effect.
Fix that using extended version of this function with added argument
for disabling side effect and keep original function for compatibility
with lots of frontends already using this interface and being
"tolerant" to its side effects.
One more source of event duplication is just line of code in
char-mux.c, which does far more than comment above says (obvious fix).

Signed-off-by: Artem Pisarenko <artem.k.pisarenko@gmail.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <7dde6abbd21682857f8294644013173c0b9949b3.1541507990.git.artem.k.pisarenko@gmail.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Artem Pisarenko 2018-11-06 18:40:51 +06:00 committed by Marc-André Lureau
parent 0b5e750bea
commit 7a9657ef53
3 changed files with 49 additions and 18 deletions

View file

@ -246,14 +246,15 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
}
}
void qemu_chr_fe_set_handlers(CharBackend *b,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
BackendChangeHandler *be_change,
void *opaque,
GMainContext *context,
bool set_open)
void qemu_chr_fe_set_handlers_full(CharBackend *b,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
BackendChangeHandler *be_change,
void *opaque,
GMainContext *context,
bool set_open,
bool sync_state)
{
Chardev *s;
int fe_open;
@ -285,7 +286,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
qemu_chr_fe_take_focus(b);
/* We're connecting to an already opened device, so let's make sure we
also get the open event */
if (s->be_open) {
if (sync_state && s->be_open) {
qemu_chr_be_event(s, CHR_EVENT_OPENED);
}
}
@ -295,6 +296,20 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
}
}
void qemu_chr_fe_set_handlers(CharBackend *b,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
BackendChangeHandler *be_change,
void *opaque,
GMainContext *context,
bool set_open)
{
qemu_chr_fe_set_handlers_full(b, fd_can_read, fd_read, fd_event, be_change,
opaque, context, set_open,
true);
}
void qemu_chr_fe_take_focus(CharBackend *b)
{
if (!b->chr) {