From 919a435a6bb7f878ed78807b9c1cb77a36383f85 Mon Sep 17 00:00:00 2001 From: Softer Date: Wed, 10 Jun 2026 10:10:29 +0300 Subject: [PATCH] Skip custom mirror config when keyring sync fails (#4577) * Skip custom mirror config when keyring sync fails Check the exit state of archlinux-keyring-wkd-sync.service after waiting for it to finish. If it failed, skip set_mirrors() and continue installation with default mirrors instead of crashing with "GPGME error: No data" during pacman -Syy. * Reinit keyring automatically when pacman sync fails with GPGME error Instead of skipping mirror configuration when wkd-sync fails, catch the GPGME error at the point where it actually occurs - during pacman -Syy. If the sync fails with a keyring-related error, reinit the keyring with pacman-key --init/--populate and retry the sync. * Simplify pacman sync() and guard gpg-agent kill on running state Collapse the duplicated self.ask() blocks in sync() into a single call via a msg variable, and drop the redundant default_cmd='pacman' (it is already the default). In _reinit_keyring(), check that gpg-agent is actually running (pgrep -x) before killing it, instead of catching the killall error and assuming it was not running. --- archinstall/lib/installer.py | 3 ++ archinstall/lib/pacman/pacman.py | 48 ++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index f53dcda4..985e16cd 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -228,6 +228,9 @@ class Installer: while self._service_state('archlinux-keyring-wkd-sync.service') not in ('dead', 'failed', 'exited'): time.sleep(1) + if self._service_state('archlinux-keyring-wkd-sync.service') == 'failed': + warn('archlinux-keyring-wkd-sync failed, keyring may need reinit during pacman sync') + def _verify_boot_part(self) -> None: """ Check that mounted /boot device has at minimum size for installation diff --git a/archinstall/lib/pacman/pacman.py b/archinstall/lib/pacman/pacman.py index c78f6145..83b965e2 100644 --- a/archinstall/lib/pacman/pacman.py +++ b/archinstall/lib/pacman/pacman.py @@ -4,8 +4,8 @@ from collections.abc import Callable from pathlib import Path from archinstall.lib.command import SysCommand -from archinstall.lib.exceptions import RequirementError -from archinstall.lib.log import error, info, warn +from archinstall.lib.exceptions import RequirementError, SysCallError +from archinstall.lib.log import debug, error, info, warn from archinstall.lib.pathnames import PACMAN_CONF from archinstall.lib.plugins import plugins from archinstall.lib.translationhandler import tr @@ -53,15 +53,45 @@ class Pacman: def sync(self) -> None: if self.synced: return - self.ask( - 'Could not sync a new package database', - 'Could not sync mirrors', - self.run, - '-Syy', - default_cmd='pacman', - ) + + try: + self.run('-Syy') + except SysCallError as err: + if b'GPGME' in err.worker_log or b'keyring' in err.worker_log.lower(): + warn('Pacman sync failed with keyring error, attempting keyring reinit') + self._reinit_keyring() + msg = 'Could not sync a new package database after keyring reinit' + else: + msg = 'Could not sync a new package database' + + self.ask(msg, 'Could not sync mirrors', self.run, '-Syy') + self.synced = True + @staticmethod + def _is_running(process: str) -> bool: + try: + SysCommand(f'pgrep -x {process}') + return True + except SysCallError: + debug(f'{process} is not running') + return False + + @staticmethod + def _reinit_keyring() -> None: + if Pacman._is_running('gpg-agent'): + try: + SysCommand('killall gpg-agent') + except SysCallError as err: + debug(f'Failed to kill gpg-agent: {err}') + + try: + SysCommand('pacman-key --init') + SysCommand('pacman-key --populate archlinux') + debug('Keyring reinitialized successfully') + except SysCallError as err: + debug(f'Keyring reinit failed: {err}') + def strap(self, packages: str | list[str]) -> None: self.sync() if isinstance(packages, str):