[gnome-remote-desktop] vnc-server: Cleanup resources directly when stopping the server



commit 3343c09d49333983ff1846c13c34353e8536eec6
Author: Pascal Nowack <Pascal Nowack gmx de>
Date:   Sat Feb 26 13:25:51 2022 +0100

    vnc-server: Cleanup resources directly when stopping the server
    
    To stop the VNC server, gnome-remote-desktop currently calls
    grd_vnc_server_stop() to stop the socket listener and then unrefs the
    server instance, where also all current VNC sessions are supposed to be
    cleaned up.
    This works fine, when just the backend is disabled, but
    gnome-remote-desktop continues to run.
    However, when the daemon is shut down, this is not the case:
    Although the server backends are cleaned up before the GrdContext
    instance, the context instance is in reality cleaned up first.
    This is visible in the form that glib does not run the dispose()
    function in the server class directly.
    The reason for this is that the GSource for the socket callback also
    has its internal reference.
    This GSource cleans up its reference, when the G_IO_NVAL value is
    returned from its fd.
    
    The effect of the current handling is that gnome-remote-desktop
    crashes, when the daemon exits.
    To prevent this crash, clean up the internal server resources in
    grd_vnc_server_stop() too.
    This ensures that the destruction order is kept and no use-after-free
    situations happen, when the daemon exits.

 src/grd-vnc-server.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)
---
diff --git a/src/grd-vnc-server.c b/src/grd-vnc-server.c
index 633fa858..0b4322d9 100644
--- a/src/grd-vnc-server.c
+++ b/src/grd-vnc-server.c
@@ -151,6 +151,17 @@ grd_vnc_server_stop (GrdVncServer *vnc_server)
 {
   g_socket_service_stop (G_SOCKET_SERVICE (vnc_server));
   g_socket_listener_close (G_SOCKET_LISTENER (vnc_server));
+
+  while (vnc_server->sessions)
+    {
+      GrdSession *session = vnc_server->sessions->data;
+
+      grd_session_stop (session);
+    }
+
+  grd_vnc_server_cleanup_stopped_sessions (vnc_server);
+  g_clear_handle_id (&vnc_server->cleanup_sessions_idle_id,
+                     g_source_remove);
 }
 
 static void
@@ -195,16 +206,9 @@ grd_vnc_server_dispose (GObject *object)
 {
   GrdVncServer *vnc_server = GRD_VNC_SERVER (object);
 
-  while (vnc_server->sessions)
-    {
-      GrdSession *session = vnc_server->sessions->data;
-
-      grd_session_stop (session);
-    }
-
-  grd_vnc_server_cleanup_stopped_sessions (vnc_server);
-  g_clear_handle_id (&vnc_server->cleanup_sessions_idle_id,
-                     g_source_remove);
+  g_assert (!vnc_server->sessions);
+  g_assert (!vnc_server->stopped_sessions);
+  g_assert (!vnc_server->cleanup_sessions_idle_id);
 
   G_OBJECT_CLASS (grd_vnc_server_parent_class)->dispose (object);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]