Commit 50eccb08 authored by Benjamin Berg's avatar Benjamin Berg Committed by Benjamin Berg

plugins: Add systemd user service files for all the plugins

Using the facility added in the previous commit, we can add systemd user
service files for all plugins and know when they have started up.

This is roughly based on the work previously done by Iain Lane
<iain@orangesquash.org.uk> and Bastien Nocera hadess@hadess.net>.

For each g-s-d process we have a service and a target file. This
separation only exists to contain dependency failures which would cause
an OnFailure action to trigger and is needed so that we can use
OnFailure for the gnome-session fail-whale
(gnome-session-failed.target).

In general, the approach taken is that we start g-s-d processes after
gnome-session-initialized.target and before gnome-session.target.

We want to be able to selectively start the services only when one or
more dependencies are there, or even mask out services under some
conditions. The approach taken is the following:
 * To mask a service, use a Conflicts entry. This is e.g. used to not
   start certain services in GDM using
     Conflicts=gnome-session@gnome-login.target
 * To depend on multiple targets to be up and running to start, we set
   each of these targets in Requisite/After/PartOf/WantedBy. We always
   do this for gnome-session-initialized.target but this method is
   extensible to any number of further targets (e.g. bluetooth.target)
parent 65253003
Pipeline #101986 passed with stages
in 7 minutes and 40 seconds
......@@ -102,6 +102,18 @@ polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.114')
upower_glib_dep = dependency('upower-glib', version: '>= 0.99.8')
x11_dep = dependency('x11')
enable_systemd = get_option('systemd')
if enable_systemd
systemd_dep = dependency('systemd', required: false)
assert(systemd_dep.found(), 'Systemd support explicitly required, but systemd not found')
# XXX: Once https://github.com/systemd/systemd/issues/9595 is fixed and we can
# depend on this version, replace with something like:
# systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir')
# and uncomment systemd_dep below
systemd_userunitdir = join_paths(gsd_prefix, 'lib', 'systemd', 'user')
endif
m_dep = cc.find_library('m')
# ALSA integration (default enabled)
......@@ -252,6 +264,9 @@ output += ' RFKill support: ' + enable_rfkill.to_string() + '\n
if enable_smartcard
output += ' System nssdb: ' + system_nssdb_dir + '\n'
endif
if enable_systemd
output += ' Systemd user unit dir: ' + systemd_userunitdir + '\n'
endif
if enable_rfkill
output += ' udev dir: ' + udev_dir + '\n'
endif
......
option('nssdb_dir', type: 'string', value: '', description: 'Absolute path to the system NSS database directory')
option('udev_dir', type: 'string', value: '', description: 'Absolute path of the udev base directory')
option('systemd', type: 'boolean', value: true, description: 'Enable systemd integration')
option('alsa', type: 'boolean', value: true, description: 'build with ALSA support (not optional on Linux platforms)')
option('gudev', type: 'boolean', value: true, description: 'build with gudev device support (not optional on Linux platforms)')
......
[Unit]
Description=GNOME Accessibility settings
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-a11y-settings.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-a11y-settings
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Accessibility settings
BindsTo=gsd-a11y-settings.service
After=gsd-a11y-settings.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
[Unit]
Description=GNOME Color management
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-color.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-color
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Color management
BindsTo=gsd-color.service
After=gsd-color.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
......@@ -40,37 +40,6 @@ static GOptionEntry entries[] = {
{NULL}
};
static const char *gdm_helpers[] = {
"a11y-keyboard",
"a11y-settings",
"clipboard",
"color",
"keyboard",
"media-keys",
"power",
"smartcard",
"sound",
"xsettings",
"wacom",
};
static gboolean
should_run (void)
{
const char *session_mode;
guint i;
session_mode = g_getenv ("GNOME_SHELL_SESSION_MODE");
if (g_strcmp0 (session_mode, "gdm") != 0)
return TRUE;
for (i = 0; i < G_N_ELEMENTS (gdm_helpers); i++) {
if (g_str_equal (PLUGIN_NAME, gdm_helpers[i]))
return TRUE;
}
return FALSE;
}
static void
respond_to_end_session (GDBusProxy *proxy)
{
......@@ -242,7 +211,7 @@ name_lost_cb (GDBusConnection *connection,
int
main (int argc, char **argv)
{
GError *error;
GError *error = NULL;
guint name_own_id;
bindtextdomain (GETTEXT_PACKAGE, GNOME_SETTINGS_LOCALEDIR);
......@@ -291,14 +260,11 @@ main (int argc, char **argv)
manager = NEW ();
register_with_gnome_session ();
if (should_run ()) {
error = NULL;
if (!START (manager, &error)) {
fprintf (stderr, "Failed to start: %s\n", error->message);
g_error_free (error);
exit (1);
}
}
if (!START (manager, &error)) {
fprintf (stderr, "Failed to start: %s\n", error->message);
g_error_free (error);
exit (1);
}
name_own_id = g_bus_own_name (G_BUS_TYPE_SESSION,
PLUGIN_DBUS_NAME,
......@@ -311,8 +277,7 @@ main (int argc, char **argv)
gtk_main ();
if (should_run ())
STOP (manager);
STOP (manager);
g_object_unref (manager);
g_bus_unown_name (name_own_id);
......
......@@ -43,36 +43,6 @@ static GOptionEntry entries[] = {
{NULL}
};
static const char *gdm_helpers[] = {
"a11y-keyboard",
"a11y-settings",
"clipboard",
"color",
"keyboard",
"media-keys",
"power",
"smartcard",
"sound",
"xsettings"
};
static gboolean
should_run (void)
{
const char *session_mode;
guint i;
session_mode = g_getenv ("GNOME_SHELL_SESSION_MODE");
if (g_strcmp0 (session_mode, "gdm") != 0)
return TRUE;
for (i = 0; i < G_N_ELEMENTS (gdm_helpers); i++) {
if (g_str_equal (PLUGIN_NAME, gdm_helpers[i]))
return TRUE;
}
return FALSE;
}
static void
respond_to_end_session (GDBusProxy *proxy)
{
......@@ -268,14 +238,11 @@ main (int argc, char **argv)
manager = NEW ();
register_with_gnome_session (loop);
if (should_run ()) {
error = NULL;
if (!START (manager, &error)) {
fprintf (stderr, "Failed to start: %s\n", error->message);
g_error_free (error);
exit (1);
}
}
if (!START (manager, &error)) {
fprintf (stderr, "Failed to start: %s\n", error->message);
g_error_free (error);
exit (1);
}
name_own_id = g_bus_own_name (G_BUS_TYPE_SESSION,
PLUGIN_DBUS_NAME,
......@@ -288,8 +255,7 @@ main (int argc, char **argv)
g_main_loop_run (loop);
if (should_run ())
STOP (manager);
STOP (manager);
g_object_unref (manager);
g_bus_unown_name (name_own_id);
......
[Unit]
Description=GNOME Date & Time handling
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-datetime.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-datetime
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Date & Time handling
BindsTo=gsd-datetime.service
After=gsd-datetime.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
Conflicts=gnome-session@gnome-login.target
Conflicts=gnome-session@gnome-initial-setup.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
[Unit]
Description=GNOME Settings Daemon dummy replacement plugin (@pluginname@)
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-dummy.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-dummy --dummy-name=@pluginname@
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Settings Daemon dummy replacement plugin (@pluginname@)
BindsTo=gsd-dummy.service
After=gsd-dummy.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
# See require-started.target on how to require another unit to be already running
# See dependency.target on how to start a dependency and require it to be present
#
#Requisite=require-started.target
#After=require-started.target
#PartOf=require-started.target
#Requires=dependency.target
#After=dependency.target
#
# Also add PartOf if this unit should be stopped together with dependency.target
#PartOf=dependency.target
# This is what the install section would look like, but we create the symlinks
# through meson
#[Install]
#WantedBy=gnome-session-initialized.target
##WantedBy=require-started.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
[Unit]
Description=GNOME Maintenance of expirable data
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-housekeeping.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-housekeeping
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Maintenance of expirable data
BindsTo=gsd-housekeeping.service
After=gsd-housekeeping.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
Conflicts=gnome-session@gnome-login.target
Conflicts=gnome-session@gnome-initial-setup.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
[Unit]
Description=GNOME Keyboard handling
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-keyboard.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-keyboard
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Keyboard handling
BindsTo=gsd-keyboard.service
After=gsd-keyboard.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
[Unit]
Description=GNOME Media keys handling
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-media-keys.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-media-keys
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Media keys handling
BindsTo=gsd-media-keys.service
After=gsd-media-keys.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
#!/bin/sh
set -eu
# Script copied from systemd
unitdir="$1"
target="$2"
unit="$3"
case "$target" in
*/?*) # a path, but not just a slash at the end
dir="${DESTDIR:-}${target}"
;;
*)
dir="${DESTDIR:-}${unitdir}/${target}"
;;
esac
unitpath="${DESTDIR:-}${unitdir}/${unit}"
case "$target" in
*/)
mkdir -vp -m 0755 "$dir"
;;
*)
mkdir -vp -m 0755 "$(dirname "$dir")"
;;
esac
ln -vfs --relative "$unitpath" "$dir"
enabled_plugins = [
['a11y-settings', 'A11ySettings'],
['color', 'Color'],
['a11y-settings', 'A11ySettings', ''],
['color', 'Color', ''],
['datetime', 'Datetime'],
['dummy', ''],
['power', 'Power'],
......@@ -18,7 +18,7 @@ if enable_smartcard
endif
if enable_wacom
enabled_plugins += [['wacom', 'Wacom']]
enabled_plugins += [['wacom', 'Wacom', 'wacom.target.wants/']]
endif
if enable_cups
......@@ -33,33 +33,89 @@ if enable_wwan
enabled_plugins += [['wwan', 'Wwan']]
endif
plugin_install_extra_wants = {
# 'dummy': ['required-started.target.wants/'],
# 'xsettings': ['gnome-session-x11.target.wants/'],
# 'wacom': ['wacom.target.wants/'],
# 'smartcard': ['smartcard.target.wants/'],
}
plugins_conf = configuration_data()
plugins_conf.set('libexecdir', gsd_libexecdir)
plugins_conf.set('systemd_hidden', enable_systemd ? 'true' : 'false')
plugins_deps = [libgsd_dep]
plugins_cflags = ['-DGNOME_SETTINGS_LOCALEDIR="@0@"'.format(gsd_localedir)]
enabled_plugins_file = []
foreach plugin: [['common', '']] + enabled_plugins
plugin_name = plugin[0]
plugin_dbus_name = plugin[1]
desktop = 'org.gnome.SettingsDaemon.@0@.desktop'.format(plugin[1])
if plugin[1] == '' # common or dummy
desktop_in_file = ''
else
desktop_in_file = files(join_paths(plugin_name, desktop + '.in'))
endif
enabled_plugins_file += [[plugin_name, plugin[1], desktop_in_file]]
endforeach
foreach plugin: enabled_plugins_file
plugin_name = plugin[0]
plugin_name_case = plugin[1]
plugin_dbus_name='org.gnome.SettingsDaemon.@0@'.format(plugin_name_case)
cflags = [
'-DG_LOG_DOMAIN="@0@-plugin"'.format(plugin_name),
'-DPLUGIN_NAME="@0@"'.format(plugin_name),
'-DPLUGIN_DBUS_NAME="org.gnome.SettingsDaemon.@0@"'.format(plugin_dbus_name),
'-DPLUGIN_DBUS_NAME="@0@"'.format(plugin_dbus_name),
] + plugins_cflags
if not ['common', 'dummy'].contains(plugin_name)
desktop = 'org.gnome.SettingsDaemon.@0@.desktop'.format(plugin[1])
desktop_in_file = plugin[2]
user_target = 'gsd-@0@.target'.format(plugin_name)
user_service = 'gsd-@0@.service'.format(plugin_name)
unit_conf = configuration_data()
unit_conf.set('libexecdir', gsd_libexecdir)
unit_conf.set('plugin_dbus_name', plugin_dbus_name)
configure_file(
input: join_paths(plugin_name, desktop + '.in'),
input: desktop_in_file,
output: desktop,
configuration: plugins_conf,
install: true,
install_dir: gsd_xdg_autostart
)
if enable_systemd
configure_file(
input: join_paths(plugin_name, user_service + '.in'),
output: user_service,
configuration: unit_conf,
install: true,
install_dir: systemd_userunitdir
)
configure_file(
input: join_paths(plugin_name, user_target + '.in'),
output: user_target,
configuration: unit_conf,
install: true,
install_dir: systemd_userunitdir
)
wants = ['gnome-session-initialized.target.wants/']
if plugin_name in plugin_install_extra_wants
wants += [plugin_install_extra_wants[plugin_name]]
endif
foreach target: wants
meson.add_install_script('meson-add-wants.sh', systemd_userunitdir, target, user_target)
endforeach
endif
endif
subdir(plugin_name)
......
[Unit]
Description=GNOME Power management handling
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-power.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-power
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Power management handling
BindsTo=gsd-power.service
After=gsd-power.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
[Unit]
Description=GNOME Printer notifications
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-print-notifications.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-print-notifications
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Printer notifications
BindsTo=gsd-print-notifications.service
After=gsd-print-notifications.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
[Unit]
Description=GNOME RFKill handling
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-rfkill.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-rfkill
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME RFKill handling
BindsTo=gsd-rfkill.service
After=gsd-rfkill.service
Requisite=gnome-session-initialized.target
After=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session.target
......@@ -7,3 +7,4 @@ NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true
X-GNOME-HiddenUnderSystemd=@systemd_hidden@
[Unit]
Description=GNOME Freedesktop screensaver handling
# Note that we do the shenanigans with having a target and a service solely
# so that OnFailure is not called in case of a dependency failure.
# See also https://github.com/systemd/systemd/issues/12352
OnFailure=gnome-session-failed.target
CollectMode=inactive-or-failed
RefuseManualStart=true
RefuseManualStop=true
PartOf=gsd-screensaver-proxy.target
After=gnome-session-initialized.target
[Service]
Type=dbus
ExecStart=@libexecdir@/gsd-screensaver-proxy
Restart=on-failure
BusName=@plugin_dbus_name@
[Unit]
Description=GNOME Freedesktop screensaver handling