From 36f0b52bb23d731e2ea4ae4c82deeee44305a7b5 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 24 Mar 2023 12:47:37 -0400 Subject: [PATCH] Fix delay during boot for some users Resolves: #2180768 --- 0001-daemon-Fix-boot-delay.patch | 340 +++++++++++++++++++++++++++++++ accountsservice.spec | 8 +- 2 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 0001-daemon-Fix-boot-delay.patch diff --git a/0001-daemon-Fix-boot-delay.patch b/0001-daemon-Fix-boot-delay.patch new file mode 100644 index 0000000..c0c7c6e --- /dev/null +++ b/0001-daemon-Fix-boot-delay.patch @@ -0,0 +1,340 @@ +From bef4aa0d07924e22c0689d5308802b576d756e19 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 24 Mar 2023 12:16:46 -0400 +Subject: [PATCH] daemon: Fix boot delay + +commit 836a9135fe2d8fdc7d6de3a6d11fb9a5fd05f926 made accountsservice +reload wtmp less aggressively. + +Unfortunately, if wtmp is modified during boot, that added latency +and delay the user list getting loaded. + +This commit addresses the problem by tracking how pressing the queued +reload operation is, and makes it happen sooner if a higher priority +request comes in. +--- + src/daemon.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/src/daemon.c b/src/daemon.c +index 151f294..9209976 100644 +--- a/src/daemon.c ++++ b/src/daemon.c +@@ -43,79 +43,89 @@ + #include + #include + #include + #include + + #include "user-classify.h" + #include "wtmp-helper.h" + #include "daemon.h" + #include "util.h" + #include "user.h" + #include "accounts-user-generated.h" + + #define PATH_PASSWD "passwd" + #define PATH_SHADOW "shadow" + #define PATH_GROUP "/etc/group" + #define PATH_DM "/etc/systemd/system/display-manager.service" + + enum + { + PROP_0, + PROP_DAEMON_VERSION + }; + + typedef enum + { + DISPLAY_MANAGER_TYPE_NONE = -1, + DISPLAY_MANAGER_TYPE_GDM, + DISPLAY_MANAGER_TYPE_LIGHTDM + } DisplayManagerType; + ++typedef enum ++{ ++ USER_RELOAD_TYPE_NONE = 0, ++ USER_RELOAD_TYPE_IMMEDIATELY, ++ USER_RELOAD_TYPE_SOON, ++ USER_RELOAD_TYPE_EVENTUALLY ++} UserReloadType; ++ + typedef struct + { + GDBusConnection *bus_connection; + + GHashTable *users; + gsize number_of_normal_users; + GList *explicitly_requested_users; + + User *autologin; + + GFileMonitor *passwd_monitor; + GFileMonitor *shadow_monitor; + GFileMonitor *group_monitor; + GFileMonitor *dm_monitor; + GFileMonitor *wtmp_monitor; + + GQueue *pending_list_cached_users; + ++ UserReloadType reload_type; + guint reload_id; ++ + guint autologin_id; + + PolkitAuthority *authority; + GHashTable *extension_ifaces; + } DaemonPrivate; + + typedef struct passwd * (* EntryGeneratorFunc) (Daemon *, + GHashTable *, + GHashTable *, + gpointer *, + struct spwd **shadow_entry); + + typedef struct + { + Daemon *daemon; + GDBusMethodInvocation *context; + } ListUserData; + + static void finish_list_cached_users (ListUserData *data); + + static void list_user_data_free (ListUserData *data); + + static void daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface); + + G_DEFINE_TYPE_WITH_CODE (Daemon, daemon, ACCOUNTS_TYPE_ACCOUNTS_SKELETON, G_ADD_PRIVATE (Daemon) G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_ACCOUNTS, daemon_accounts_accounts_iface_init)); + + G_DEFINE_AUTOPTR_CLEANUP_FUNC (Daemon, g_object_unref) + + static const GDBusErrorEntry accounts_error_entries[] = + { +@@ -598,60 +608,61 @@ reload_users (Daemon *daemon) + user_unregister (user); + } + } + + /* Register all the new users */ + g_hash_table_iter_init (&iter, users); + while (g_hash_table_iter_next (&iter, &name, &value)) { + User *user = value; + User *stale_user; + + stale_user = g_hash_table_lookup (old_users, name); + + if (!stale_user || (!user_get_cached (stale_user) && user_get_cached (user))) { + user_register (user); + accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon), + user_get_object_path (user)); + } + g_object_thaw_notify (G_OBJECT (user)); + } + + g_hash_table_destroy (old_users); + } + + static gboolean + reload_users_timeout (Daemon *daemon) + { + DaemonPrivate *priv = daemon_get_instance_private (daemon); + + reload_users (daemon); + priv->reload_id = 0; ++ priv->reload_type = USER_RELOAD_TYPE_NONE; + + g_queue_foreach (priv->pending_list_cached_users, + (GFunc) finish_list_cached_users, NULL); + g_queue_clear (priv->pending_list_cached_users); + + return FALSE; + } + + static gboolean load_autologin (Daemon *daemon, + gchar **name, + gboolean *enabled, + GError **error); + + static gboolean + reload_autologin_timeout (Daemon *daemon) + { + DaemonPrivate *priv = daemon_get_instance_private (daemon); + AccountsAccounts *accounts = ACCOUNTS_ACCOUNTS (daemon); + gboolean enabled; + g_autofree gchar *name = NULL; + + g_autoptr (GError) error = NULL; + User *user = NULL; + + priv->autologin_id = 0; + + if (!load_autologin (daemon, &name, &enabled, &error)) { + g_debug ("failed to load autologin conf file: %s", error->message); + return FALSE; + } +@@ -671,87 +682,100 @@ reload_autologin_timeout (Daemon *daemon) + users[0] = user_get_object_path (user); + users[1] = NULL; + accounts_accounts_set_automatic_login_users (accounts, users); + if (priv->autologin != user) { + g_object_set (user, "automatic-login", TRUE, NULL); + priv->autologin = g_object_ref (user); + g_signal_emit_by_name (priv->autologin, "changed", 0); + } + } else { + g_debug ("automatic login is disabled"); + accounts_accounts_set_automatic_login_users (accounts, NULL); + } + + return FALSE; + } + + static void + queue_reload_users_eventually (Daemon *daemon) + { + DaemonPrivate *priv = daemon_get_instance_private (daemon); + + if (priv->reload_id > 0) { + return; + } + + /* we wait 10 seconds before reloading the users, so e.g. wtmp + * parsing doesn't hammer the cpu if the user is logging in + * and out in a continuous loop. + */ + priv->reload_id = g_timeout_add_seconds (10, (GSourceFunc) reload_users_timeout, daemon); ++ priv->reload_type = USER_RELOAD_TYPE_EVENTUALLY; + } + + static void + queue_reload_users_soon (Daemon *daemon) + { + DaemonPrivate *priv = daemon_get_instance_private (daemon); + ++ if (priv->reload_type > USER_RELOAD_TYPE_SOON) { ++ g_source_remove (priv->reload_id); ++ priv->reload_id = 0; ++ } ++ + if (priv->reload_id > 0) { + return; + } + + /* we wait half a second or so in case /etc/passwd and + * /etc/shadow are changed at the same time, or repeatedly. + */ + priv->reload_id = g_timeout_add (500, (GSourceFunc) reload_users_timeout, daemon); ++ priv->reload_type = USER_RELOAD_TYPE_SOON; + } + + static void + queue_reload_users (Daemon *daemon) + { + DaemonPrivate *priv = daemon_get_instance_private (daemon); + ++ if (priv->reload_type > USER_RELOAD_TYPE_IMMEDIATELY) { ++ g_source_remove (priv->reload_id); ++ priv->reload_id = 0; ++ } ++ + if (priv->reload_id > 0) { + return; + } + + priv->reload_id = g_idle_add ((GSourceFunc) reload_users_timeout, daemon); ++ priv->reload_type = USER_RELOAD_TYPE_IMMEDIATELY; + } + + static void + queue_reload_autologin (Daemon *daemon) + { + DaemonPrivate *priv = daemon_get_instance_private (daemon); + + if (priv->autologin_id > 0) { + return; + } + + priv->autologin_id = g_idle_add ((GSourceFunc) reload_autologin_timeout, daemon); + } + + static void + on_users_monitor_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + Daemon *daemon) + { + DaemonPrivate *priv = daemon_get_instance_private (daemon); + + if (event_type != G_FILE_MONITOR_EVENT_CHANGED && + event_type != G_FILE_MONITOR_EVENT_CREATED) { + return; + } + + if (monitor == priv->wtmp_monitor) { + queue_reload_users_eventually (daemon); +@@ -1120,60 +1144,61 @@ finish_list_cached_users (ListUserData *data) + } + + if (!user_get_cached (user)) { + g_debug ("user %s %ld not cached", name, (long) uid); + continue; + } + + g_debug ("user %s %ld not excluded", name, (long) uid); + g_ptr_array_add (object_paths, (gpointer) user_get_object_path (user)); + } + g_ptr_array_add (object_paths, NULL); + + accounts_accounts_complete_list_cached_users (NULL, data->context, (const gchar * const *) object_paths->pdata); + + list_user_data_free (data); + } + + static gboolean + daemon_list_cached_users (AccountsAccounts *accounts, + GDBusMethodInvocation *context) + { + Daemon *daemon = (Daemon *) accounts; + DaemonPrivate *priv = daemon_get_instance_private (daemon); + ListUserData *data; + + data = list_user_data_new (daemon, context); + + if (priv->reload_id > 0) { + /* reload pending -- finish call in reload_users_timeout */ + g_queue_push_tail (priv->pending_list_cached_users, data); ++ queue_reload_users (daemon); + } else { + finish_list_cached_users (data); + } + + return TRUE; + } + + static int + sort_languages (gconstpointer element_1, + gconstpointer element_2, + GHashTable *language_frequency_map) + { + const char *language_1 = *(const char **) element_1; + const char *language_2 = *(const char **) element_2; + int count_1, count_2; + + count_1 = GPOINTER_TO_INT (g_hash_table_lookup (language_frequency_map, language_1)); + count_2 = GPOINTER_TO_INT (g_hash_table_lookup (language_frequency_map, language_2)); + + if (count_2 == count_1) { + return strcmp (language_1, language_2); + } + + return count_2 - count_1; + } + + static gboolean + daemon_get_users_languages (AccountsAccounts *accounts, + GDBusMethodInvocation *context) + { +-- +2.39.2 + diff --git a/accountsservice.spec b/accountsservice.spec index 750e829..f574e16 100644 --- a/accountsservice.spec +++ b/accountsservice.spec @@ -1,6 +1,6 @@ Name: accountsservice Version: 23.11.69 -Release: 1%{?dist} +Release: 2%{?dist} Summary: D-Bus interfaces for querying and manipulating user account information License: GPLv3+ URL: https://www.freedesktop.org/wiki/Software/AccountsService/ @@ -11,6 +11,8 @@ Source1: https://storage.googleapis.com/google-code-archive-downloads/v2/ # https://wrapdb.mesonbuild.com/v1/projects/mocklibc/1.0/2/get_zip Source2: mocklibc-1.0-2-wrap.zip +Patch0: 0001-daemon-Fix-boot-delay.patch + BuildRequires: gettext-devel BuildRequires: pkgconfig(dbus-1) BuildRequires: glib2-devel @@ -117,6 +119,10 @@ mkdir -p $RPM_BUILD_ROOT%{_datadir}/accountsservice/interfaces/ %{_datadir}/vala/vapi/accountsservice.* %changelog +* Fri Mar 24 2023 Ray Strode - 23.11.69-2 +- Fix delay during boot for some users + Resolves: #2180768 + * Wed Mar 15 2023 Ray Strode - 23.11.69-1 - Update to 23.11.69