On Wed, Jul 01, 2026 at 08:32:06AM +0200, Markus Armbruster wrote:
> [email protected] writes:
> 
> >> The default monitor is usually a long lived object that will exist for
> >> the entire lifetime of the VM. A monitor can only service a single
> >> client at a time though, and so it might be desirable to hotplug
> >> additional monitors at runtime for specific tasks. If doing that,
> >> however, there is a need to remove the monitor when it is no longer
> >> needed.
> 
> Whatever adds the additional monitor can also delete it.  The fact that
> you propose other means suggests you believe this would be cumbersome in
> practice.  Why?
> 
> >> 
> >> Allowing a client to run "object-del" against its own monitor adds
> >> complex edge cases, as it would be desirable to send the QMP response
> >> despite the monitor sending it being deleted. Doing "object-del" alone
> >> will also result in orphaning a character device backend instance, as
> >> there is no opportunity to run the companion "chardev-del" command.
> >> 
> >> A simpler way to ensure cleanup is to add the concept of auto-deleting
> >> monitor objects. Specifically when the "CHR_EVENT_CLOSED" event is
> >> emitted, the equivalent of "object-del" + "chardev-del" can be run
> >> internally. Since the transient client has already droppped its
> >> monitor connection, there is no synchronization to be concerned about.
> 
> If object-del or chardev-del fail, there's no way to report the error.
> Can they fail?
> 
> Do we always want to delete both monitor and character device?
> 
> >> This is implemented via a new "close-action=none|delete" property on
> >> the 'monitor-qmp' object. This concept could be extended with further
> >> actions in future, for example:
> >> 
> >>  * close-action=shutdown - graceful guest shutdown
> >>  * close-action=terminate - immediate guest poweroff
> >>  * close-action=stop - pause guest CPUs while the monitor is not
> >>                        connected to any client
> 
> I'm not sure these would be useful and safe.  Mentioning them here is
> okay regardless.
> 
> >> 
> >> This is left as an exercise for future interested contributors.
> >> 
> >> Tested-by: Peter Krempa <[email protected]>
> >> Signed-off-by: Daniel P. Berrangé <[email protected]>
> >> Message-ID: <[email protected]>

snip

> >> diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
> >> index 5522e05464b..23829f32f9a 100644
> >> --- a/monitor/monitor-internal.h
> >> +++ b/monitor/monitor-internal.h

snip

> >> +static void monitor_qmp_self_delete_bh(void *opaque)
> >> +{
> >> +    MonitorQMP *mon = opaque;
> >> +    g_autofree char *mon_id = object_property_get_child_name(
> >> +        object_get_objects_root(), OBJECT(mon));
> >> +    g_autofree char *chardev_id = g_strdup(mon->parent_obj.chardev_id);
> >> +    Error *local_error = NULL;
> >> +
> >> +    if (!mon_id) {
> >> +        /* Another monitor raced & ran 'object-del' on 'mon'
> >> +         * before this BH got scheduled, so we have a ref on
> >> +         * mon but it is already unparented.
> >> +         */
> >> +        object_unref(mon);
> >> +        return;
> >> +    }
> >> +
> >> +    user_creatable_del(mon_id, &local_error);
> >> +    object_unref(mon);
> 
> This object_unref() and the one above pair with the object_ref() in
> monitor_qmp_event() case MONITOR_QMP_CLOSE_ACTION_DELETE.  Correct?
> 
> Is this worth a comment?
> 
> >> +    if (local_error != NULL) {
> >> +        error_report_err(local_error);
> >> +    } else {
> >> +        qmp_chardev_remove(chardev_id, NULL);
> >> +    }
> >> +}
> >> +
> >>  static void monitor_qmp_event(void *opaque, QEMUChrEvent event)
> >>  {
> >>      QDict *data;
> >>      MonitorQMP *mon = opaque;
> >>  
> >> +    /* Protect against race if a client drops & quickly
> >> +     * reconnects - we'll have the delete BH scheduled
> >> +     * so must not honour a new open request
> >> +     */
> >> +    if (mon->delete_pending) {
> >> +        return;
> >> +    }
> 
> Consider "something happens between setting @delete_pending and monitor
> destruction that triggers the event" and "same thing happens after
> destruction".  Any observable differences in behavior?
> 
> Are there any other monitor interactions that might need similar
> special-casing when @delete_pending?

When the BH deletes the monitor object, it will disconnect the
chardev handlers. So there is no possibility of monitor_qmp_event
being called after the monitor QOM destruction is complete. The
only race is between this method and the start of the BH.

With regards,
Daniel
-- 
|: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
|: https://libvirt.org          ~~          https://entangle-photo.org :|
|: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|

Reply via email to