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>
This commit is contained in:
Nishal Kulkarni 2021-08-05 20:05:18 +05:30 committed by Florian Müllner
parent 4a0c86ea4c
commit c2efe25597
2 changed files with 86 additions and 0 deletions

View File

@ -565,6 +565,9 @@ struct _MetaWindow
guint unmanage_idle_id; guint unmanage_idle_id;
pid_t client_pid; pid_t client_pid;
gboolean has_valid_cgroup;
GFile *cgroup_path;
}; };
struct _MetaWindowClass struct _MetaWindowClass
@ -890,4 +893,8 @@ gboolean meta_window_shortcuts_inhibited (MetaWindow *window,
ClutterInputDevice *source); ClutterInputDevice *source);
gboolean meta_window_is_stackable (MetaWindow *window); gboolean meta_window_is_stackable (MetaWindow *window);
gboolean meta_window_is_focus_async (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 #endif

View File

@ -97,6 +97,10 @@
#include "wayland/meta-window-xwayland.h" #include "wayland/meta-window-xwayland.h"
#endif #endif
#ifdef HAVE_LIBSYSTEMD
#include <systemd/sd-login.h>
#endif
/* Windows that unmaximize to a size bigger than that fraction of the workarea /* Windows that unmaximize to a size bigger than that fraction of the workarea
* will be scaled down to that size (while maintaining aspect ratio). * will be scaled down to that size (while maintaining aspect ratio).
* Windows that cover an area greater then this size are automaximized on map. * 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) if (window->transient_for)
g_object_unref (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->sm_client_id);
g_free (window->wm_client_machine); g_free (window->wm_client_machine);
g_free (window->startup_id); g_free (window->startup_id);
@ -1157,6 +1164,9 @@ _meta_window_shared_new (MetaDisplay *display,
window->client_pid = 0; window->client_pid = 0;
window->has_valid_cgroup = TRUE;
window->cgroup_path = NULL;
window->xtransient_for = None; window->xtransient_for = None;
window->xclient_leader = None; window->xclient_leader = None;
@ -7736,6 +7746,75 @@ meta_window_get_pid (MetaWindow *window)
return window->client_pid; 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: * meta_window_get_client_machine:
* @window: a #MetaWindow * @window: a #MetaWindow