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.
This commit is contained in:
Softer 2026-06-10 10:10:29 +03:00 committed by GitHub
parent 091665a975
commit 919a435a6b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 9 deletions

View File

@ -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

View File

@ -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):