From: Christian Brauner <brauner@kernel.org>
Convert monitor_accept_input from a oneshot BH (aio_bh_schedule_oneshot)
to a persistent BH (aio_bh_new + qemu_bh_schedule). Oneshot BHs cannot
be cancelled, so monitor_resume() racing with destruction would schedule
a callback against memory that monitor_qmp_destroy() is about to free.
A persistent BH can be deleted during destruction, cancelling any
pending schedule.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
[DB: extracted oneshot BH conversion from larger commit]
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Tested-by: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
monitor/monitor-internal.h | 2 +-
monitor/monitor.c | 25 ++++++++++++++-----------
2 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index 012d442a20..a82e1aacb6 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -134,7 +134,7 @@ struct Monitor {
char *chardev_id;
CharFrontend chr;
int suspend_cnt; /* Needs to be accessed atomically */
-
+ QEMUBH *accept_input_bh; /* persistent BH for monitor_accept_input */
char *mon_cpu_path;
QTAILQ_ENTRY(Monitor) entry;
diff --git a/monitor/monitor.c b/monitor/monitor.c
index f0ca6b04ed..de1f761041 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -83,6 +83,9 @@ static void monitor_finalize(Object *obj)
{
Monitor *mon = MONITOR(obj);
+ if (mon->accept_input_bh) {
+ qemu_bh_delete(mon->accept_input_bh);
+ }
g_free(mon->chardev_id);
g_free(mon->mon_cpu_path);
qemu_chr_fe_deinit(&mon->chr, false);
@@ -569,15 +572,7 @@ static void monitor_accept_input(void *opaque)
void monitor_resume(Monitor *mon)
{
if (qatomic_dec_fetch(&mon->suspend_cnt) == 0) {
- AioContext *ctx;
-
- if (monitor_requires_iothread(mon)) {
- ctx = iothread_get_aio_context(mon_iothread);
- } else {
- ctx = qemu_get_aio_context();
- }
-
- aio_bh_schedule_oneshot(ctx, monitor_accept_input, mon);
+ qemu_bh_schedule(mon->accept_input_bh);
}
trace_monitor_suspend(mon, -1);
@@ -700,6 +695,7 @@ char *monitor_compat_id(void)
static void monitor_complete(UserCreatable *uc, Error **errp)
{
Monitor *mon = MONITOR(uc);
+ AioContext *ctx;
if (mon->chardev_id) {
Chardev *chr = qemu_chr_find(mon->chardev_id);
@@ -713,9 +709,16 @@ static void monitor_complete(UserCreatable *uc, Error **errp)
}
}
- if (monitor_requires_iothread(mon) && !mon_iothread) {
- mon_iothread = iothread_create("mon_iothread", &error_abort);
+ if (monitor_requires_iothread(mon)) {
+ if (!mon_iothread) {
+ mon_iothread = iothread_create("mon_iothread", &error_abort);
+ }
+
+ ctx = iothread_get_aio_context(mon_iothread);
+ } else {
+ ctx = qemu_get_aio_context();
}
+ mon->accept_input_bh = aio_bh_new(ctx, monitor_accept_input, mon);
}
int monitor_new(MonitorOptions *opts, bool allow_hmp, Error **errp)
--
2.55.0