[plasma/kscreenlocker] greeter: pamauthenticator: detect slow broken services more reliably

Harald Sitter <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit cc1ee1ad5cbd13a1ec7f6fd9f040fea357ad3277 by Harald Sitter.
Committed on 18/08/2026 at 11:15.
Pushed by sitter into branch 'master'.

pamauthenticator: detect slow broken services more reliably

M  +19   -1    greeter/pamauthenticator.cpp
M  +2    -0    greeter/pamauthenticator.h

https://invent.kde.org/plasma/kscreenlocker/-/commit/cc1ee1ad5cbd13a1ec7f6fd9f040fea357ad3277

diff --git a/greeter/pamauthenticator.cpp b/greeter/pamauthenticator.cpp
index 32c454f8..833405da 100644
--- a/greeter/pamauthenticator.cpp
+++ b/greeter/pamauthenticator.cpp
@@ -62,7 +62,25 @@ PamAuthenticator::PamAuthenticator(const QString &service, const QString &user,
     });
     // Failed is not a persistent state. When a view provides authentication that will either result in failure or success,
     // failure simply means that the prompt is getting delayed.
-    connect(d, &PamWorker::failed, this, &PamAuthenticator::failed);
+    connect(d, &PamWorker::failed, this, [this] {
+        // Guard against particularly broken PAM services. For example when pam-u2f doesn't find a token because it is
+        // not plugged in it will fail the authentication, but it will do it so slowly that the timing checks in the
+        // worker itself don't bite.
+        // Here we can keep a higher level view of the failures and if need be break the loop by marking us unavailable.
+        auto now = QDateTime::currentDateTimeUtc();
+        if (now - m_lastFailed < 2s) {
+            m_failedCount++;
+            if (m_failedCount > 3) {
+                m_unavailable = true;
+                Q_EMIT availableChanged();
+            }
+        } else {
+            m_failedCount = 0;
+        }
+        m_lastFailed = now;
+
+        Q_EMIT failed();
+    });
     connect(d, &PamWorker::loginFailedDelayStarted, this, &PamAuthenticator::loginFailedDelayStarted);
 
     m_thread.start();
diff --git a/greeter/pamauthenticator.h b/greeter/pamauthenticator.h
index d3831a38..aa562f60 100644
--- a/greeter/pamauthenticator.h
+++ b/greeter/pamauthenticator.h
@@ -117,6 +117,8 @@ private:
     bool m_unlocked = false;
     bool m_unavailable = false;
     bool m_inPasswordDelay = false;
+    uint m_failedCount = 0;
+    QDateTime m_lastFailed = QDateTime::currentDateTimeUtc();
     NoninteractiveAuthenticatorTypes m_authenticatorType;
     // Tiny problem with bare bones QThread: when we shut down we want to clean up
     // our subprocess correctly, but doing that means running a function on the thread
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.