Since commit c7e1063 ("Use default DBus timeout for KWallet check", shipped in 0.16.0), isKwalletAvailable() performs a blocking networkWallet D-Bus call with the default 25-second timeout. That commit removed the previous iface.setTimeout(500) to fix #242, on the assumption that "If KWallet is not available the call will fail fast."
That assumption doesn't hold in one common case: kwalletd is running but busy showing its unlock dialog. While the dialog is up, kwalletd holds replies to incoming calls, so the blocking call neither succeeds nor fails fast; it blocks the calling thread for the full 25 seconds.
Backend detection runs lazily on the first job's scheduledStart(), which is typically the application's GUI thread. The result:
- Any Qt app using QtKeychain 0.16.0+ that starts while the wallet is locked (e.g. autostarted apps at session login before the user has entered the wallet password) freezes for 25 s.
- In our case (a Plasma applet, so QtKeychain runs inside plasmashell), the entire desktop shell froze for 25 s at every login until the wallet was unlocked.
Steps to reproduce
- KDE Plasma 6, wallet configured with a password, not unlocked by PAM.
- Start an application that issues a
ReadPasswordJob at startup, while the wallet unlock dialog from another client is pending (or before unlocking).
- Application GUI thread blocks ~25 s in
detectKeyringBackend() → isKwalletAvailable().
Suggested fix
Cap the probe timeout again, but treat a timeout as "available" so the concern from #242 (slow kwalletd misdetected as absent silent libsecret fallback, cached for the process lifetime) stays fixed: a timeout proves the service exists; it's just busy.
--- a/qtkeychain/keychain_unix.cpp
+++ b/qtkeychain/keychain_unix.cpp
@@ -103,8 +103,17 @@ static bool isKwalletAvailable(const char *dbusIface, const char *dbusPath)
// interface is activatable by making a call. Hence we check whether
// a wallet can be opened.
+ iface.setTimeout(5000);
QDBusMessage reply = iface.call(QLatin1String("networkWallet"));
- return reply.type() == QDBusMessage::ReplyMessage;
+ if (reply.type() == QDBusMessage::ReplyMessage)
+ return true;
+ const QDBusError::ErrorType err = QDBusError(reply).type();
+ return err == QDBusError::NoReply || err == QDBusError::Timeout;
}
static KeyringBackend detectKeyringBackend()
This is tested and working; the login freeze is gone, and backend selection still resolves to KWallet with the wallet locked. The remaining 5 s stall could be eliminated by making detection async, but that's a much larger structural change; this keeps the current shape of the code.
Related: #242 (the issue the regressing commit fixed).
Since commit c7e1063 ("Use default DBus timeout for KWallet check", shipped in 0.16.0),
isKwalletAvailable()performs a blockingnetworkWalletD-Bus call with the default 25-second timeout. That commit removed the previousiface.setTimeout(500)to fix #242, on the assumption that "If KWallet is not available the call will fail fast."That assumption doesn't hold in one common case: kwalletd is running but busy showing its unlock dialog. While the dialog is up, kwalletd holds replies to incoming calls, so the blocking call neither succeeds nor fails fast; it blocks the calling thread for the full 25 seconds.
Backend detection runs lazily on the first job's
scheduledStart(), which is typically the application's GUI thread. The result:Steps to reproduce
ReadPasswordJobat startup, while the wallet unlock dialog from another client is pending (or before unlocking).detectKeyringBackend()→isKwalletAvailable().Suggested fix
Cap the probe timeout again, but treat a timeout as "available" so the concern from #242 (slow kwalletd misdetected as absent silent libsecret fallback, cached for the process lifetime) stays fixed: a timeout proves the service exists; it's just busy.
This is tested and working; the login freeze is gone, and backend selection still resolves to KWallet with the wallet locked. The remaining 5 s stall could be eliminated by making detection async, but that's a much larger structural change; this keeps the current shape of the code.
Related: #242 (the issue the regressing commit fixed).