@samitouri / QOSamiQemu / commits / 94c64bfb44

monitor: convert from oneshot BH to persistent BH

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> Message-ID: <20260706135824.2623960-25-berrange@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Christian Brauner committed Jul 6, 2026 at 14:58 UTC 94c64bfb44db0a8530c5c92ac73a16b225ebb4d8
2 files changed +15 -12
monitor/monitor-internal.h
+1 -1
@@ -134,7 +134,7 @@ struct Monitor {
134 char *chardev_id;
135 CharFrontend chr;
136 int suspend_cnt; /* Needs to be accessed atomically */
137 -
137 + QEMUBH *accept_input_bh; /* persistent BH for monitor_accept_input */
138 char *mon_cpu_path;
139 QTAILQ_ENTRY(Monitor) entry;
140
monitor/monitor.c
+14 -11
@@ -83,6 +83,9 @@ static void monitor_finalize(Object *obj)
83 {
84 Monitor *mon = MONITOR(obj);
85
86 + if (mon->accept_input_bh) {
87 + qemu_bh_delete(mon->accept_input_bh);
88 + }
89 g_free(mon->chardev_id);
90 g_free(mon->mon_cpu_path);
91 qemu_chr_fe_deinit(&mon->chr, false);
@@ -569,15 +572,7 @@ static void monitor_accept_input(void *opaque)
572 void monitor_resume(Monitor *mon)
573 {
574 if (qatomic_dec_fetch(&mon->suspend_cnt) == 0) {
572 - AioContext *ctx;
573 -
574 - if (monitor_requires_iothread(mon)) {
575 - ctx = iothread_get_aio_context(mon_iothread);
576 - } else {
577 - ctx = qemu_get_aio_context();
578 - }
579 -
580 - aio_bh_schedule_oneshot(ctx, monitor_accept_input, mon);
575 + qemu_bh_schedule(mon->accept_input_bh);
576 }
577
578 trace_monitor_suspend(mon, -1);
@@ -700,6 +695,7 @@ char *monitor_compat_id(void)
695 static void monitor_complete(UserCreatable *uc, Error **errp)
696 {
697 Monitor *mon = MONITOR(uc);
698 + AioContext *ctx;
699
700 if (mon->chardev_id) {
701 Chardev *chr = qemu_chr_find(mon->chardev_id);
@@ -713,9 +709,16 @@ static void monitor_complete(UserCreatable *uc, Error **errp)
709 }
710 }
711
716 - if (monitor_requires_iothread(mon) && !mon_iothread) {
717 - mon_iothread = iothread_create("mon_iothread", &error_abort);
712 + if (monitor_requires_iothread(mon)) {
713 + if (!mon_iothread) {
714 + mon_iothread = iothread_create("mon_iothread", &error_abort);
715 + }
716 +
717 + ctx = iothread_get_aio_context(mon_iothread);
718 + } else {
719 + ctx = qemu_get_aio_context();
720 }
721 + mon->accept_input_bh = aio_bh_new(ctx, monitor_accept_input, mon);
722 }
723
724 int monitor_new(MonitorOptions *opts, bool allow_hmp, Error **errp)