From: Christian Brauner <[email protected]>

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) <[email protected]>
[DB: extracted oneshot BH conversion from larger commit]
Signed-off-by: Daniel P. Berrangé <[email protected]>
---
 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

Reply via email to