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] 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 9257dae0be..19a119fc71 100644 --- a/monitor/monitor.c +++ b/monitor/monitor.c @@ -81,6 +81,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); @@ -566,15 +569,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); @@ -690,6 +685,7 @@ void monitor_init_globals(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); @@ -703,9 +699,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.54.0