184
}
185
}
186
187
+static void monitor_qmp_drain_queue(MonitorQMP *mon)
188
+{
189
+ QEMU_LOCK_GUARD(&mon->qmp_queue_lock);
190
+ monitor_qmp_cleanup_req_queue_locked(mon);
191
+}
192
+
193
static void monitor_qmp_cleanup_queue_and_resume(MonitorQMP *mon)
194
{
195
QEMU_LOCK_GUARD(&mon->qmp_queue_lock);
603
monitor_qmp_read, monitor_qmp_event,
604
NULL, &mon->parent_obj, context, true);
605
monitor_list_append(&mon->parent_obj);
606
+ qatomic_set(&mon->setup_pending, false);
607
}
608
609
void monitor_new_qmp(const char *id, const char *chardev_id,
651
* since chardev might be running in the monitor I/O
652
* thread. Schedule a bottom half.
653
*/
654
+ mon->setup_pending = true;
655
aio_bh_schedule_oneshot(iothread_get_aio_context(mon_iothread),
656
monitor_qmp_setup_handlers_bh, mon);
657
/* The bottom half will add @mon to @mon_list */
663
}
664
}
665
666
+static void monitor_qmp_iothread_quiesce(void *opaque)
667
+{
668
+ /* No-op: synchronization point only */
669
+}
670
+
671
static bool monitor_qmp_prepare_delete(UserCreatable *uc, Error **errp)
672
{
673
+ Monitor *mon = MONITOR(uc);
674
MonitorQMP *qmp = MONITOR_QMP(uc);
675
676
if (monitor_qmp_dispatcher_is_servicing(qmp)) {
678
return false;
679
}
680
667
- error_setg(errp, "Deleting QMP monitors is not supported");
668
- return false;
681
+ if (qatomic_read(&qmp->setup_pending)) {
682
+ error_setg(errp, "monitor is still initializing");
683
+ return false;
684
+ }
685
+
686
+ /* Remove from mon_list before chardev disconnect. */
687
+ WITH_QEMU_LOCK_GUARD(&monitor_lock) {
688
+ QTAILQ_REMOVE(&mon_list, mon, entry);
689
+ }
690
+
691
+ /* Cancel out_watch while gcontext still points to the right ctx. */
692
+ WITH_QEMU_LOCK_GUARD(&mon->mon_lock) {
693
+ monitor_cancel_out_watch(mon);
694
+ }
695
+
696
+ qemu_chr_fe_set_handlers(&mon->chr, NULL, NULL, NULL, NULL,
697
+ NULL, NULL, true);
698
+
699
+ /* Drain requests from any in-flight monitor_qmp_read(). */
700
+ monitor_qmp_drain_queue(qmp);
701
+
702
+ WITH_QEMU_LOCK_GUARD(&mon->mon_lock) {
703
+ /* Disable flushes before cancel -- gcontext is already wrong. */
704
+ qemu_chr_fe_set_open(&mon->chr, false);
705
+ monitor_cancel_out_watch(mon);
706
+ }
707
+
708
+ /* Synchronize with in-flight iothread callbacks. */
709
+ if (monitor_requires_iothread(mon)) {
710
+ aio_wait_bh_oneshot(iothread_get_aio_context(mon_iothread),
711
+ monitor_qmp_iothread_quiesce, NULL);
712
+ }
713
+
714
+ /* Catch requests from a racing monitor_qmp_read(). */
715
+ monitor_qmp_drain_queue(qmp);
716
+ monitor_fdsets_cleanup();
717
+
718
+ return true;
719
}
720
721
static void monitor_qmp_accept_input(Monitor *mon)