[gnome-shell/benzea/systemd-scopes: 1/3] utils: Add utility function to place a PID into a systemd scope
- From: Benjamin Berg <bberg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/benzea/systemd-scopes: 1/3] utils: Add utility function to place a PID into a systemd scope
- Date: Wed, 27 Nov 2019 15:43:27 +0000 (UTC)
commit e0bd7883f6dc565e9a38725afd725daeddb50661
Author: Benjamin Berg <bberg redhat com>
Date: Tue Nov 26 19:44:43 2019 +0100
utils: Add utility function to place a PID into a systemd scope
If we put children into their own scope, then we can fix a number of
issues that we were seeing with systemd managed sessions.
This will fix two bis issues, the first one that a child getting killed
by OOM was affecting the gnome-shell service (setting OOMPolicy would
also work). The second issue is that a full restart of gnome-shell (e.g.
after a crash) would also kill all children.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/863
src/shell-util.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/shell-util.h | 4 +++
2 files changed, 97 insertions(+)
---
diff --git a/src/shell-util.c b/src/shell-util.c
index f344ec50bb..765a3c22e3 100644
--- a/src/shell-util.c
+++ b/src/shell-util.c
@@ -28,6 +28,7 @@
#ifdef HAVE_SYSTEMD
#include <systemd/sd-daemon.h>
+#include <systemd/sd-login.h>
#else
/* So we don't need to add ifdef's everywhere */
#define sd_notify(u, m) do {} while (0)
@@ -632,6 +633,98 @@ shell_util_stop_systemd_unit (const char *unit,
return shell_util_systemd_call ("StopUnit", unit, mode, error);
}
+
+gboolean
+shell_util_start_systemd_scope (const gchar *app_id,
+ gint32 pid,
+ GError **error)
+{
+#ifdef HAVE_SYSTEMD
+ GVariantBuilder builder;
+ const char *valid_chars =
+ "-._1234567890"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ g_autofree gchar *mangled_app_id = NULL;
+ g_autofree gchar *unit_name = NULL;
+ g_autofree gchar *own_unit = NULL;
+ g_autoptr (GDBusConnection) connection = NULL;
+ gint res;
+
+ /* We cannot do anything if this process is not managed by the
+ * systemd user instance. */
+ res = sd_pid_get_user_unit (getpid (), &own_unit);
+ if (res == -ENODATA) {
+ g_debug ("Not systemd managed, will not move PID %d into transient scope\n", pid);
+ return TRUE;
+ }
+ if (res < 0) {
+ g_propagate_error (error,
+ g_error_new (G_IO_ERROR,
+ g_io_error_from_errno (-res),
+ "Error fetching user unit for own pid: %d", -res));
+
+ return FALSE;
+ }
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
+
+ if (connection == NULL)
+ return FALSE;
+
+ g_debug ("Trying to create transient scope for PID %d\n", pid);
+
+ /* Create a nice and (mangled) name to embed into the unit */
+ if (app_id == NULL)
+ app_id = "anonymous";
+ if (app_id[0] == '/')
+ app_id++;
+
+ mangled_app_id = g_str_to_ascii (app_id, "C");
+ g_strdelimit (mangled_app_id, "/", '-');
+ g_strcanon (mangled_app_id, valid_chars, '_');
+
+ /* This needs to be unique, hopefully the pid will be enough. */
+ unit_name = g_strdup_printf ("gnome-launched-%s-%d.scope", mangled_app_id, pid);
+
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssa(sv)a(sa(sv)))"));
+ g_variant_builder_add (&builder, "s", unit_name);
+ g_variant_builder_add (&builder, "s", "fail");
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sv)"));
+ /* Note that futher settings are controlled using a drop-in. */
+ g_variant_builder_add (&builder,
+ "(sv)",
+ "Description",
+ g_variant_new_string ("Application launched by gnome-shell"));
+ g_variant_builder_add (&builder,
+ "(sv)",
+ "PIDs",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, &pid, 1, 4));
+
+ g_variant_builder_close (&builder);
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sa(sv))"));
+ g_variant_builder_close (&builder);
+
+ g_dbus_connection_call (connection,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartTransientUnit",
+ g_variant_builder_end (&builder),
+ G_VARIANT_TYPE ("(o)"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ 1000,
+ NULL,
+ on_systemd_call_cb,
+ (gpointer) "StartTransientUnit");
+#endif
+
+ return TRUE;
+}
+
void
shell_util_sd_notify (void)
{
diff --git a/src/shell-util.h b/src/shell-util.h
index acd031048f..a7e69cfd62 100644
--- a/src/shell-util.h
+++ b/src/shell-util.h
@@ -64,6 +64,10 @@ gboolean shell_util_stop_systemd_unit (const char *unit,
const char *mode,
GError **error);
+gboolean shell_util_start_systemd_scope (const gchar *app_id,
+ gint32 pid,
+ GError **error);
+
void shell_util_sd_notify (void);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]