summaryrefslogtreecommitdiff
path: root/chardev
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2017-11-03 16:28:23 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2017-12-21 09:30:32 +0100
commitd09c4a47874f30820b08c39ad39bcca9b8cde084 (patch)
tree63451b0f382ccf605a509f3873ec44bbe10008b2 /chardev
parent5a22ab71623c0fb709d49df353bdf2ec7c445c4c (diff)
chardev: fix backend events regression with mux chardev
Kirill noticied that on recent versions on QEMU he was not able to trigger SysRq to invoke debug capabilites of Linux Kernel. He tracked it down to qemu_chr_be_event() ignoring CHR_EVENT_BREAK due s->be being NULL. The bug was introduced in 2.8, commit a4afa548fc6d ("char: move front end handlers in CharBackend"). Since the commit, the qemu_chr_be_event() failed to deliver CHR_EVENT_BREAK due to qemu_chr_fe_init() does not set s->be in case of mux. Let's fix this by teaching mux to send an event to the frontend with the focus. Reported-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Fixes: a4afa548fc6d ("char: move front end handlers in CharBackend") Message-Id: <20171103152824.21948-2-marcandre.lureau@redhat.com> Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'chardev')
-rw-r--r--chardev/char-mux.c10
-rw-r--r--chardev/char.c18
2 files changed, 22 insertions, 6 deletions
diff --git a/chardev/char-mux.c b/chardev/char-mux.c
index 4cda5e7458..567bf965cd 100644
--- a/chardev/char-mux.c
+++ b/chardev/char-mux.c
@@ -123,6 +123,15 @@ static void mux_chr_send_event(MuxChardev *d, int mux_nr, int event)
}
}
+static void mux_chr_be_event(Chardev *chr, int event)
+{
+ MuxChardev *d = MUX_CHARDEV(chr);
+
+ if (d->focus != -1) {
+ mux_chr_send_event(d, d->focus, event);
+ }
+}
+
static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch)
{
if (d->term_got_escape) {
@@ -346,6 +355,7 @@ static void char_mux_class_init(ObjectClass *oc, void *data)
cc->chr_write = mux_chr_write;
cc->chr_accept_input = mux_chr_accept_input;
cc->chr_add_watch = mux_chr_add_watch;
+ cc->chr_be_event = mux_chr_be_event;
}
static const TypeInfo char_mux_type_info = {
diff --git a/chardev/char.c b/chardev/char.c
index 2ae4f465ec..8c3765ee99 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -43,10 +43,19 @@ static Object *get_chardevs_root(void)
return container_get(object_get_root(), "/chardevs");
}
-void qemu_chr_be_event(Chardev *s, int event)
+static void chr_be_event(Chardev *s, int event)
{
CharBackend *be = s->be;
+ if (!be || !be->chr_event) {
+ return;
+ }
+
+ be->chr_event(be->opaque, event);
+}
+
+void qemu_chr_be_event(Chardev *s, int event)
+{
/* Keep track if the char device is open */
switch (event) {
case CHR_EVENT_OPENED:
@@ -57,11 +66,7 @@ void qemu_chr_be_event(Chardev *s, int event)
break;
}
- if (!be || !be->chr_event) {
- return;
- }
-
- be->chr_event(be->opaque, event);
+ CHARDEV_GET_CLASS(s)->chr_be_event(s, event);
}
/* Not reporting errors from writing to logfile, as logs are
@@ -244,6 +249,7 @@ static void char_class_init(ObjectClass *oc, void *data)
ChardevClass *cc = CHARDEV_CLASS(oc);
cc->chr_write = null_chr_write;
+ cc->chr_be_event = chr_be_event;
}
static void char_finalize(Object *obj)