Hi

On Mon, Apr 28, 2025 at 12:06 PM Dietmar Maurer <diet...@proxmox.com> wrote:
>
> Some encoders can hang indefinitely (i.e. nvh264enc) if
> the pipeline is not stopped before it is destroyed
> (Observed on Debian bookworm).
>
> Signed-off-by: Dietmar Maurer <diet...@proxmox.com>

In file included from /home/elmarco/src/qemu/include/ui/console.h:4,
                 from ../system/runstate.c:54:
/home/elmarco/src/qemu/include/ui/qemu-pixman.h:10:10: fatal error:
pixman.h: No such file or directory
   10 | #include <pixman.h>
      |          ^~~~~~~~~~

Also it will have to handle the case when !CONFIG_VNC (can probably
use a stub cleanup function)

> ---
>  include/ui/console.h |  1 +
>  system/runstate.c    |  2 ++
>  ui/vnc-enc-h264.c    | 18 ++++++++++++++++++
>  ui/vnc.c             | 15 +++++++++++++++
>  4 files changed, 36 insertions(+)
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 46b3128185..ff46e9fe98 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -458,6 +458,7 @@ int vnc_display_password(const char *id, const char 
> *password);
>  int vnc_display_pw_expire(const char *id, time_t expires);
>  void vnc_parse(const char *str);
>  int vnc_init_func(void *opaque, QemuOpts *opts, Error **errp);
> +void vnc_cleanup(void);
>  bool vnc_display_reload_certs(const char *id,  Error **errp);
>  bool vnc_display_update(DisplayUpdateOptionsVNC *arg, Error **errp);
>
> diff --git a/system/runstate.c b/system/runstate.c
> index 272801d307..4b2c6f3525 100644
> --- a/system/runstate.c
> +++ b/system/runstate.c
> @@ -51,6 +51,7 @@
>  #include "qemu/thread.h"
>  #include "qom/object.h"
>  #include "qom/object_interfaces.h"
> +#include "ui/console.h"
>  #include "system/cpus.h"
>  #include "system/qtest.h"
>  #include "system/replay.h"
> @@ -924,6 +925,7 @@ void qemu_cleanup(int status)
>      job_cancel_sync_all();
>      bdrv_close_all();
>
> +    vnc_cleanup();
>      /* vhost-user must be cleaned up before chardevs.  */
>      tpm_cleanup();
>      net_cleanup();
> diff --git a/ui/vnc-enc-h264.c b/ui/vnc-enc-h264.c
> index 98055c095f..6618f156b4 100644
> --- a/ui/vnc-enc-h264.c
> +++ b/ui/vnc-enc-h264.c
> @@ -95,6 +95,24 @@ static GstElement *create_encoder(const char *encoder_name)
>
>  static void destroy_encoder_context(VncState *vs)
>  {
> +    GstStateChangeReturn state_change_ret;
> +
> +    VNC_DEBUG("Destroy h264 context.\n");
> +
> +    /*
> +     * Some encoders can hang indefinitely (i.e. nvh264enc) if
> +     * the pipeline is not stopped before it is destroyed
> +     * (Observed on Debian bookworm).
> +     */
> +    if (vs->h264->pipeline != NULL) {
> +        state_change_ret = gst_element_set_state(
> +            vs->h264->pipeline, GST_STATE_NULL);
> +
> +        if (state_change_ret == GST_STATE_CHANGE_FAILURE) {
> +            VNC_DEBUG("Unable to stop the GST pipeline\n");
> +        }
> +    }
> +
>      gst_clear_object(&vs->h264->source);
>      gst_clear_object(&vs->h264->convert);
>      gst_clear_object(&vs->h264->gst_encoder);
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 2d1e741705..062d6af0ab 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -4366,6 +4366,21 @@ int vnc_init_func(void *opaque, QemuOpts *opts, Error 
> **errp)
>      return 0;
>  }
>
> +void vnc_cleanup(void)
> +{
> +    VncDisplay *vd;
> +    VncState *vs;
> +
> +    QTAILQ_FOREACH(vd, &vnc_displays, next) {
> +        QTAILQ_FOREACH(vs, &vd->clients, next) {
> +#ifdef CONFIG_GSTREAMER
> +            /* correctly close all h264 encoder pipelines */
> +            vnc_h264_clear(vs);
> +#endif
> +        }
> +    }
> +}
> +
>  static void vnc_register_config(void)
>  {
>      qemu_add_opts(&qemu_vnc_opts);
> --
> 2.39.5
>
>


-- 
Marc-André Lureau

Reply via email to