[mutter] window: Add cgroup management to MetaWindow



commit c2efe255972a3a29e1e2ba5fde5519440aaba653
Author: Nishal Kulkarni <nishalkulkarni gmail com>
Date:   Thu Aug 5 20:05:18 2021 +0530

    window: Add cgroup management to MetaWindow
    
    Currently the only way to get cgroup for a MetaWindow is to get it's
    PID and perform a bunch of file accesses and string manipulations.
    This is especially not feasible if we want to get the cgroup every
    time a MetaWindow has gained or lost focus.
    
    A solution to this is to cache the GFile for a cgroup path.
    The creation and access of this GFile is handled by
    `meta_window_get_unit_cgroup` function.
    
    `meta_window_unit_cgroup_equal` is a utility function which allows
    us to compare whether two MetaWindows belong to the same cgroup.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1960>

 src/core/window-private.h |  7 +++++
 src/core/window.c         | 79 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+)
---
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 18f62d1f45..3bd75fe47a 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -565,6 +565,9 @@ struct _MetaWindow
   guint unmanage_idle_id;
 
   pid_t client_pid;
+
+  gboolean has_valid_cgroup;
+  GFile *cgroup_path;
 };
 
 struct _MetaWindowClass
@@ -890,4 +893,8 @@ gboolean meta_window_shortcuts_inhibited (MetaWindow         *window,
                                           ClutterInputDevice *source);
 gboolean meta_window_is_stackable (MetaWindow *window);
 gboolean meta_window_is_focus_async (MetaWindow *window);
+
+GFile *meta_window_get_unit_cgroup (MetaWindow *window);
+gboolean meta_window_unit_cgroup_equal (MetaWindow *window1,
+                                        MetaWindow *window2);
 #endif
diff --git a/src/core/window.c b/src/core/window.c
index b23f66e814..e543814179 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -97,6 +97,10 @@
 #include "wayland/meta-window-xwayland.h"
 #endif
 
+#ifdef HAVE_LIBSYSTEMD
+#include <systemd/sd-login.h>
+#endif
+
 /* Windows that unmaximize to a size bigger than that fraction of the workarea
  * will be scaled down to that size (while maintaining aspect ratio).
  * Windows that cover an area greater then this size are automaximized on map.
@@ -332,6 +336,9 @@ meta_window_finalize (GObject *object)
   if (window->transient_for)
     g_object_unref (window->transient_for);
 
+  if (window->cgroup_path)
+    g_object_unref (window->cgroup_path);
+
   g_free (window->sm_client_id);
   g_free (window->wm_client_machine);
   g_free (window->startup_id);
@@ -1157,6 +1164,9 @@ _meta_window_shared_new (MetaDisplay         *display,
 
   window->client_pid = 0;
 
+  window->has_valid_cgroup = TRUE;
+  window->cgroup_path = NULL;
+
   window->xtransient_for = None;
   window->xclient_leader = None;
 
@@ -7736,6 +7746,75 @@ meta_window_get_pid (MetaWindow *window)
   return window->client_pid;
 }
 
+/**
+ * meta_window_get_unit_cgroup:
+ * @window: a #MetaWindow
+ *
+ * Return value: a GFile for the cgroup path, or NULL.
+ */
+GFile *
+meta_window_get_unit_cgroup (MetaWindow *window)
+{
+#ifdef HAVE_LIBSYSTEMD
+  g_autofree char *contents = NULL;
+  g_autofree char *complete_path = NULL;
+  g_autofree char *unit_name = NULL;
+  g_autofree char *unit_path = NULL;
+  char *unit_end;
+  pid_t pid;
+
+  if (!window->has_valid_cgroup)
+    return NULL;
+
+  if (window->cgroup_path)
+    return window->cgroup_path;
+
+  pid = meta_window_get_pid (window);
+  if (pid < 1)
+    return NULL;
+
+  if (sd_pid_get_cgroup (pid, &contents) < 0)
+    {
+      window->has_valid_cgroup = FALSE;
+      return NULL;
+    }
+  g_strstrip (contents);
+
+  complete_path = g_strdup_printf ("%s%s", "/sys/fs/cgroup", contents);
+
+  if (sd_pid_get_user_unit (pid, &unit_name) < 0)
+    {
+      window->has_valid_cgroup = FALSE;
+      return NULL;
+    }
+  g_strstrip (unit_name);
+
+  unit_end = strstr (complete_path, unit_name) + strlen (unit_name);
+  *unit_end = '\0';
+
+  window->cgroup_path = g_file_new_for_path (complete_path);
+
+  return window->cgroup_path;
+#else
+  return NULL;
+#endif
+}
+
+gboolean
+meta_window_unit_cgroup_equal (MetaWindow *window1,
+                               MetaWindow *window2)
+{
+  GFile *window1_file, *window2_file;
+
+  window1_file = meta_window_get_unit_cgroup (window1);
+  window2_file = meta_window_get_unit_cgroup (window2);
+
+  if (!window1_file || !window2_file)
+    return FALSE;
+
+  return g_file_equal (window1_file, window2_file);
+}
+
 /**
  * meta_window_get_client_machine:
  * @window: a #MetaWindow


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