parent
818c77f6ef
commit
36f0b52bb2
340
0001-daemon-Fix-boot-delay.patch
Normal file
340
0001-daemon-Fix-boot-delay.patch
Normal file
@ -0,0 +1,340 @@
|
||||
From bef4aa0d07924e22c0689d5308802b576d756e19 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
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 <glib-object.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gio/gio.h>
|
||||
#include <polkit/polkit.h>
|
||||
|
||||
#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
|
||||
|
||||
@ -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 <rstrode@redhat.com> - 23.11.69-2
|
||||
- Fix delay during boot for some users
|
||||
Resolves: #2180768
|
||||
|
||||
* Wed Mar 15 2023 Ray Strode <rstrode@redhat.com> - 23.11.69-1
|
||||
- Update to 23.11.69
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user