diff options
author | Benjamin Berg <bberg@redhat.com> | 2019-10-04 17:09:18 +0200 |
---|---|---|
committer | Benjamin Berg <bberg@redhat.com> | 2019-10-04 17:11:34 +0200 |
commit | 20948032bafe839d95bbf48c78cf45bc40fde8d9 (patch) | |
tree | e313e4831955e5eab37a7d5d8a7e90f42694af70 | |
parent | 14abdd1bcfc1c96c2cfe16f8995a59972ee2999a (diff) | |
download | gnome-session-benzea/systemd-issue-35.tar.gz |
Delay XDG autostart applications on systemdbenzea/systemd-issue-35
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
-rw-r--r-- | data/gnome-session-initialized.target | 4 | ||||
-rw-r--r-- | data/gnome-session-manager@.service.in | 2 | ||||
-rw-r--r-- | data/gnome-session-signal-phase@.service.in (renamed from data/gnome-session-signal-init.service.in) | 2 | ||||
-rw-r--r-- | data/gnome-session.target | 6 | ||||
-rw-r--r-- | data/meson.build | 2 | ||||
-rw-r--r-- | gnome-session/gsm-manager.c | 58 | ||||
-rw-r--r-- | gnome-session/org.gnome.SessionManager.xml | 9 | ||||
-rw-r--r-- | tools/gnome-session-ctl.c | 16 |
8 files changed, 63 insertions, 36 deletions
diff --git a/data/gnome-session-initialized.target b/data/gnome-session-initialized.target index 3ef2ecfe..959a83c0 100644 --- a/data/gnome-session-initialized.target +++ b/data/gnome-session-initialized.target @@ -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 diff --git a/data/gnome-session-manager@.service.in b/data/gnome-session-manager@.service.in index b06dbeb3..13bfc73d 100644 --- a/data/gnome-session-manager@.service.in +++ b/data/gnome-session-manager@.service.in @@ -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 diff --git a/data/gnome-session-signal-init.service.in b/data/gnome-session-signal-phase@.service.in index e3d2c463..84c40b55 100644 --- a/data/gnome-session-signal-init.service.in +++ b/data/gnome-session-signal-phase@.service.in @@ -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 diff --git a/data/gnome-session.target b/data/gnome-session.target index 55cfc751..ba7ba3f4 100644 --- a/data/gnome-session.target +++ b/data/gnome-session.target @@ -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 diff --git a/data/meson.build b/data/meson.build index ef35c494..647483a3 100644 --- a/data/meson.build +++ b/data/meson.build @@ -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'] diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c index d41bdcac..1e1a1ed3 100644 --- a/gnome-session/gsm-manager.c +++ b/gnome-session/gsm-manager.c @@ -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", diff --git a/gnome-session/org.gnome.SessionManager.xml b/gnome-session/org.gnome.SessionManager.xml index ce4b8c07..be792306 100644 --- a/gnome-session/org.gnome.SessionManager.xml +++ b/gnome-session/org.gnome.SessionManager.xml @@ -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> diff --git a/tools/gnome-session-ctl.c b/tools/gnome-session-ctl.c index 9276a0ad..7f46955c 100644 --- a/tools/gnome-session-ctl.c +++ b/tools/gnome-session-ctl.c @@ -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) { |