gpg 2.5.24 hangs in exit() after a trustdb error when keyboxd is in use
Bryan Lee
hi at looping.me
Sat Oct 10 10:21:47 CEST 2026
Hi,
With use-keyboxd, gpg never exits after a fatal trustdb error during
signature verification. It looks like a reproducer for the atexit
lockup that libgpg-error 50f0c56 addressed and ff90817 reverted.
GnuPG 2.5.24, libgpg-error 1.61, libgcrypt 1.12.4, libassuan 3.0.2,
libksba 1.8.1, npth 1.8 (Homebrew, macOS 27.0.1 on arm64).
To reproduce, as a normal user in an empty directory:
export GNUPGHOME=$PWD/gh
mkdir -m 700 gh && echo use-keyboxd > gh/common.conf
gpg --batch --passphrase '' --quick-gen-key test at example.org ed25519 sign never
echo hello > msg
gpg --batch -u test at example.org --detach-sign msg
gpg --verify msg.sig msg
cp gh/trustdb.gpg tdb.gpg && chmod 000 tdb.gpg
gpg --trustdb-name ./tdb.gpg --verify msg.sig msg
The first --verify succeeds and exits. The second prints
gpg: Signature made Sat Oct 10 15:04:04 2026 +08
gpg: using EDDSA key 088FF601942A662BE0DDFD2A18289422E990E6C2
gpg: issuer "test at example.org"
gpg: Fatal: can't open './tdb.gpg': Permission denied
and then hangs, in 5 of 5 runs. In a homedir that uses pubring.kbx
instead of keyboxd, the same fatal error exits with status 2 right away.
A macOS `sample` of the hung process shows (abridged):
main thread: open_db -> gpgrt_log_fatal -> exit -> do_deinit
-> _gpgrt_fflush -> _gpgrt_lock_lock
second thread: datastream_thread -> _gpgrt_read -> es_readn
-> do_read_fbf -> func_fd_read -> read
My reading of the code: do_deinit calls _gpgrt_fflush (NULL, 1), which
takes every stream's lock, while datastream_thread holds the lock on
kcd->fp inside es_read as it waits for keyboxd. At the end of main(),
gpg_deinit_default_ctrl releases the keyboxd session (the assuan
connection first) before g10_exit (0), so the thread finishes. log_fatal
calls exit() without that cleanup, and a g10_exit (2) on an error path
skips it too. Continuing the recipe with
chmod 400 gh/trustdb.gpg
gpg --check-trustdb
prints "trustdb: sync failed: Bad file descriptor" and hangs the same
way, with do_sync -> g10_exit -> do_deinit on the main thread.
Thanks,
Bryan
More information about the Gnupg-devel
mailing list