Commit 20948032 authored by Benjamin Berg's avatar Benjamin Berg

Delay XDG autostart applications on systemd

When launching on systemd we did not synchronize the phases after
the shell is loaded. Due to this, applications may start up before g-s-d
is started, which should not be the case.

Add a further one-way synchronization point so that gnome-session only
starts launching applications after gnome-session.target has been
reached.

Fixes: #35
parent 14abdd1b
......@@ -15,5 +15,5 @@ Before=gnome-session.target
# Signal gnome-session that we reached the initialized target and
# that it may start applications.
Requires=gnome-session-signal-init.service
Before=gnome-session-signal-init.service
Requires=gnome-session-signal-phase@4.service
Before=gnome-session-signal-phase@4.service
......@@ -15,5 +15,5 @@ Before=gnome-session-manager.target
[Service]
Type=notify
ExecStart=@libexecdir@/gnome-session-binary --systemd-service --session=%i
ExecStart=@libexecdir@/gnome-session-binary --systemd-service --debug --session=%i
ExecStopPost=-@libexecdir@/gnome-session-ctl --shutdown
......@@ -5,4 +5,4 @@ PartOf=gnome-session.target
[Service]
Type=oneshot
ExecStart=@libexecdir@/gnome-session-ctl --signal-init
ExecStart=@libexecdir@/gnome-session-ctl --signal-phase=%I
......@@ -14,5 +14,11 @@ Before=graphical-session.target
BindsTo=gnome-session-monitor.service
After=gnome-session-monitor.service
# Signal gnome-session that the desktop is fully loaded at this point.
# Note that this signal is one-way only and prevents XDG autostart
# applications from loading early.
Requires=gnome-session-signal-phase@7.service
Before=gnome-session-signal-phase@7.service
# Pull in timer to mark session as stable (and unstable as long as the timer is active)
Requires=gnome-session-stable.timer
......@@ -100,7 +100,7 @@ if enable_systemd_session
systemd_userunitdir = join_paths(session_prefix, 'lib', 'systemd', 'user')
systemd_service = ['gnome-session-manager@.service',
'gnome-session-signal-init.service',
'gnome-session-signal-phase@.service',
'gnome-session-restart-dbus.service',
'gnome-session-monitor.service',
'gnome-session-failed.service']
......
......@@ -126,8 +126,8 @@ struct GsmManagerPrivate
{
gboolean failsafe;
gboolean systemd_managed;
gboolean systemd_initialized;
gboolean manager_initialized;
gint systemd_phase;
gboolean manager_waiting_systemd;
GsmStore *clients;
GsmStore *inhibitors;
GsmInhibitorFlag inhibited_actions;
......@@ -540,16 +540,24 @@ end_phase (GsmManager *manager)
case GSM_MANAGER_PHASE_DISPLAY_SERVER:
break;
case GSM_MANAGER_PHASE_INITIALIZATION:
manager->priv->manager_initialized = TRUE;
/* Wait for systemd if it isn't initialized yet*/
if (manager->priv->systemd_managed && !manager->priv->systemd_initialized) {
/* Wait for systemd to reach the same state */
if (manager->priv->systemd_managed && manager->priv->systemd_phase < GSM_MANAGER_PHASE_INITIALIZATION) {
sd_notify (0, "STATUS=GNOME Session Manager waiting for gnome-session-initialized.target (via signal)");
manager->priv->manager_waiting_systemd = TRUE;
start_next_phase = FALSE;
}
break;
case GSM_MANAGER_PHASE_WINDOW_MANAGER:
case GSM_MANAGER_PHASE_PANEL:
break;
case GSM_MANAGER_PHASE_DESKTOP:
/* Wait for systemd to reach the same state */
if (manager->priv->systemd_managed && manager->priv->systemd_phase < GSM_MANAGER_PHASE_APPLICATION) {
sd_notify (0, "STATUS=GNOME Session Manager waiting for gnome-session.target (via signal)");
manager->priv->manager_waiting_systemd = TRUE;
start_next_phase = FALSE;
}
break;
case GSM_MANAGER_PHASE_APPLICATION:
break;
case GSM_MANAGER_PHASE_RUNNING:
......@@ -2676,36 +2684,44 @@ gsm_manager_setenv (GsmExportedManager *skeleton,
}
static gboolean
gsm_manager_initialized (GsmExportedManager *skeleton,
GDBusMethodInvocation *invocation,
GsmManager *manager)
gsm_manager_systemd_phase (GsmExportedManager *skeleton,
GDBusMethodInvocation *invocation,
gint phase_done,
GsmManager *manager)
{
/* Signaled by helper when gnome-session-initialized.target is reached. */
/* Signaled by helper when gnome-session-initialized.target
* or gnome-session.target are reached. */
if (!manager->priv->systemd_managed) {
g_dbus_method_invocation_return_error (invocation,
GSM_MANAGER_ERROR,
GSM_MANAGER_ERROR_GENERAL,
"Initialized interface is only available when gnome-session is managed by systemd");
} else if (manager->priv->systemd_initialized) {
} else if (manager->priv->systemd_phase >= phase_done) {
g_dbus_method_invocation_return_error (invocation,
GSM_MANAGER_ERROR,
GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
"Systemd initialization was already signaled");
} else if (manager->priv->phase > GSM_MANAGER_PHASE_INITIALIZATION) {
"Systemd already signalled equal or higher phase");
} else if (manager->priv->phase > GSM_MANAGER_PHASE_DESKTOP) {
g_dbus_method_invocation_return_error (invocation,
GSM_MANAGER_ERROR,
GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
"Initialized interface is only available during startup");
} else {
manager->priv->systemd_initialized = TRUE;
if (manager->priv->manager_initialized) {
g_assert (manager->priv->phase == GSM_MANAGER_PHASE_INITIALIZATION);
manager->priv->phase++;
start_phase (manager);
manager->priv->systemd_phase = phase_done;
g_debug ("Systemd startup signalled phase %i as reached, waiting: %i, internal phase: %i",
phase_done,
manager->priv->manager_waiting_systemd,
manager->priv->systemd_phase);
if (manager->priv->manager_waiting_systemd) {
if (manager->priv->phase <= manager->priv->systemd_phase) {
manager->priv->manager_waiting_systemd = FALSE;
manager->priv->phase++;
start_phase (manager);
}
}
gsm_exported_manager_complete_initialized (skeleton, invocation);
gsm_exported_manager_complete_phase_done (skeleton, invocation);
}
return TRUE;
......@@ -3308,8 +3324,8 @@ register_manager (GsmManager *manager)
G_CALLBACK (gsm_manager_set_reboot_to_firmware_setup), manager);
g_signal_connect (skeleton, "handle-setenv",
G_CALLBACK (gsm_manager_setenv), manager);
g_signal_connect (skeleton, "handle-initialized",
G_CALLBACK (gsm_manager_initialized), manager);
g_signal_connect (skeleton, "handle-phase-done",
G_CALLBACK (gsm_manager_systemd_phase), manager);
g_signal_connect (skeleton, "handle-shutdown",
G_CALLBACK (gsm_manager_shutdown), manager);
g_signal_connect (skeleton, "handle-uninhibit",
......
......@@ -59,10 +59,15 @@
</doc:doc>
</method>
<method name="Initialized">
<method name="PhaseDone">
<arg type="i" name="phase" direction="in">
<doc:doc>
<doc:summary>The reached phase, must be 4 or 7 for the Initialization or Desktop phases</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Run from systemd to signal that gnome-session-initialized.target has been reached.</doc:para>
<doc:para>Run from systemd to signal that gnome-session-initialized.target or gnome-session.target have been reached.</doc:para>
</doc:description>
</doc:doc>
</method>
......
......@@ -59,7 +59,7 @@ get_session_bus (void)
}
static void
do_signal_init (void)
do_signal_phase (gint opt_signal_phase)
{
g_autoptr(GDBusConnection) connection = NULL;
g_autoptr(GVariant) reply = NULL;
......@@ -73,8 +73,8 @@ do_signal_init (void)
GSM_SERVICE_DBUS,
GSM_PATH_DBUS,
GSM_INTERFACE_DBUS,
"Initialized",
NULL,
"PhaseDone",
g_variant_new ("(i)", opt_signal_phase),
NULL,
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1, NULL, &error);
......@@ -236,14 +236,14 @@ main (int argc, char *argv[])
g_autoptr(GError) error = NULL;
static gboolean opt_shutdown;
static gboolean opt_monitor;
static gboolean opt_signal_init;
static gint opt_signal_phase;
static gboolean opt_restart_dbus;
int conflicting_options;
GOptionContext *ctx;
static const GOptionEntry options[] = {
{ "shutdown", '\0', 0, G_OPTION_ARG_NONE, &opt_shutdown, N_("Start gnome-session-shutdown.target"), NULL },
{ "monitor", '\0', 0, G_OPTION_ARG_NONE, &opt_monitor, N_("Start gnome-session-shutdown.target when receiving EOF or a single byte on stdin"), NULL },
{ "signal-init", '\0', 0, G_OPTION_ARG_NONE, &opt_signal_init, N_("Signal initialization done to gnome-session"), NULL },
{ "signal-phase", '\0', 0, G_OPTION_ARG_INT, &opt_signal_phase, N_("Signal finished phase to gnome-session"), NULL },
{ "restart-dbus", '\0', 0, G_OPTION_ARG_NONE, &opt_restart_dbus, N_("Restart dbus.service if it is running"), NULL },
{ NULL },
};
......@@ -267,7 +267,7 @@ main (int argc, char *argv[])
conflicting_options++;
if (opt_monitor)
conflicting_options++;
if (opt_signal_init)
if (opt_signal_phase)
conflicting_options++;
if (opt_restart_dbus)
conflicting_options++;
......@@ -278,8 +278,8 @@ main (int argc, char *argv[])
sd_notify (0, "READY=1");
if (opt_signal_init) {
do_signal_init ();
if (opt_signal_phase) {
do_signal_phase (opt_signal_phase);
} else if (opt_restart_dbus) {
do_restart_dbus ();
} else if (opt_shutdown) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment