on xenial help sign in
Be more emphatic about cancelling a PAM thread
commitaeb089874f93b7c05bb8de309b32889c69d06e59 authorMichael Terry <michael.terry@canonical.com> dateThu 26 Feb 2015, 15:55 (12 years ago) parent23d9094
4 files changed+101−24
plugins/LightDM/liblightdm/GreeterPrivate.cpp+14−5 plugins/LightDM/liblightdm/GreeterPrivate.h+1−1 tests/plugins/LightDM/CMakeLists.txt+35−18 tests/plugins/LightDM/pam.cpp+51
plugins/LightDM/liblightdm/GreeterPrivate.cpp+14−5
@@ -56,7 +56,8 @@ public:
5656 this, SLOT(handleMessage(pam_handle *, QString, QLightDM::Greeter::MessageType)));
5757 // This next connect is how we pass ResponseFutures between threads
5858 connect(this, SIGNAL(showPrompt(pam_handle *, QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)),
59− this, SLOT(handlePrompt(pam_handle *, QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)));
59+ this, SLOT(handlePrompt(pam_handle *, QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)),
60+ Qt::BlockingQueuedConnection);
6061 }
6162
6263 ~GreeterImpl()
@@ -79,7 +80,7 @@ public:
7980
8081 if (pam_start("lightdm", username.toUtf8(), &conversation, &pamHandle) == PAM_SUCCESS) {
8182 appData->handle = pamHandle;
82− futureWatcher.setFuture(QtConcurrent::run(authenticateWithPam, pamHandle));
83+ futureWatcher.setFuture(QtConcurrent::mapped(QList<pam_handle*>() << pamHandle, authenticateWithPam));
8384 } else {
8485 delete appData;
8586 greeterPrivate->authenticated = false;
@@ -88,7 +89,7 @@ public:
8889 }
8990 }
9091
91− static int authenticateWithPam(pam_handle* pamHandle)
92+ static int authenticateWithPam(pam_handle* const& pamHandle)
9293 {
9394 int pamStatus = pam_authenticate(pamHandle, 0);
9495 if (pamStatus == PAM_SUCCESS) {
@@ -242,11 +243,14 @@ private Q_SLOTS:
242243private:
243244 void cancelPam()
244245 {
245− // Unfortunately we can't simply cancel our QFuture because QtConcurrent::run doesn't support cancel
246246 if (pamHandle != nullptr) {
247247 pam_handle *handle = pamHandle;
248248 pamHandle = nullptr; // to disable normal finishPam() handling
249− while (respond(QString())); // clear our local queue of QFutures
249+ futureWatcher.future().cancel();
250+ while (!futureWatcher.future().isFinished()) {
251+ QCoreApplication::processEvents(); // let signal/slot handling happen
252+ respond(QString());
253+ }
250254 pam_end(handle, PAM_CONV_ERR);
251255 }
252256 }
@@ -266,6 +270,11 @@ GreeterPrivate::GreeterPrivate(Greeter* parent)
266270{
267271}
268272
273+GreeterPrivate::~GreeterPrivate()
274+{
275+ delete m_impl;
276+}
277+
269278void GreeterPrivate::handleAuthenticate()
270279{
271280 m_impl->start(authenticationUser);
plugins/LightDM/liblightdm/GreeterPrivate.h+1−1
@@ -30,7 +30,7 @@ class GreeterPrivate
3030{
3131public:
3232 explicit GreeterPrivate(Greeter* parent=0);
33− virtual ~GreeterPrivate() = default;
33+ virtual ~GreeterPrivate();
3434
3535 // These variables may not be used by all subclasses, that's no problem
3636 bool authenticated;
tests/plugins/LightDM/CMakeLists.txt+35−18
@@ -1,35 +1,52 @@
1+add_definitions(
2+ -DCURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
3+ )
4+include_directories(
5+ ${CMAKE_CURRENT_BINARY_DIR}
6+ )
7+
18add_executable(GreeterDBusTestExec
29 dbus.cpp
310 ${CMAKE_SOURCE_DIR}/plugins/LightDM/Greeter.cpp
411 )
512qt5_use_modules(GreeterDBusTestExec Core DBus Quick Test)
6−
7−add_executable(GreeterUsersModelTestExec
8− usersmodel.cpp
9− ${CMAKE_SOURCE_DIR}/plugins/LightDM/UsersModel.cpp
10− ${CMAKE_SOURCE_DIR}/plugins/Utils/unitysortfilterproxymodelqml.cpp
13+target_link_libraries(GreeterDBusTestExec
14+ -L${CMAKE_BINARY_DIR}/tests/mocks/LightDM/liblightdm
15+ -llightdm-qt5-2
1116 )
12−qt5_use_modules(GreeterUsersModelTestExec Core Test)
13−
14−include_directories(
15− ${CMAKE_CURRENT_BINARY_DIR}
17+target_include_directories(GreeterDBusTestExec PUBLIC
1618 ${CMAKE_SOURCE_DIR}/plugins/LightDM
17− ${CMAKE_SOURCE_DIR}/plugins/Utils
1819 ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM
1920 )
21+add_binary_qml_test(GreeterDBus "${CMAKE_BINARY_DIR}/tests/mocks/LightDM/liblightdm" MockLightDM "QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks")
2022
21−target_link_libraries(GreeterDBusTestExec
22− -L${CMAKE_BINARY_DIR}/tests/mocks/LightDM/liblightdm
23− -llightdm-qt5-2
23+add_executable(GreeterPamTestExec
24+ pam.cpp
25+ ${CMAKE_SOURCE_DIR}/plugins/LightDM/liblightdm/GreeterPrivate.cpp
26+ )
27+qt5_use_modules(GreeterPamTestExec Concurrent Core Test)
28+target_link_libraries(GreeterPamTestExec
29+ integratedLightDM
30+ )
31+target_include_directories(GreeterPamTestExec PUBLIC
32+ ${CMAKE_SOURCE_DIR}/plugins/LightDM/liblightdm
2433 )
34+add_qmltest_target(testGreeterPam "${CMAKE_CURRENT_BINARY_DIR}/GreeterPamTestExec" TRUE FALSE)
35+add_dependencies(testGreeterPam GreeterPamTestExec)
2536
37+add_executable(GreeterUsersModelTestExec
38+ usersmodel.cpp
39+ ${CMAKE_SOURCE_DIR}/plugins/LightDM/UsersModel.cpp
40+ ${CMAKE_SOURCE_DIR}/plugins/Utils/unitysortfilterproxymodelqml.cpp
41+ )
42+qt5_use_modules(GreeterUsersModelTestExec Core Test)
2643target_link_libraries(GreeterUsersModelTestExec
2744 -L${CMAKE_BINARY_DIR}/tests/mocks/LightDM/liblightdm
2845 -llightdm-qt5-2
2946 )
30−
31−add_definitions(-DCURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
32−
33−add_binary_qml_test(GreeterDBus "${CMAKE_BINARY_DIR}/tests/mocks/LightDM/liblightdm" MockLightDM "QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks")
34−
47+target_include_directories(GreeterUsersModelTestExec PUBLIC
48+ ${CMAKE_SOURCE_DIR}/plugins/LightDM
49+ ${CMAKE_SOURCE_DIR}/plugins/Utils
50+ ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM
51+ )
3552add_binary_qml_test(GreeterUsersModel "${CMAKE_BINARY_DIR}/tests/mocks/LightDM/liblightdm" MockLightDM "LIBLIGHTDM_MOCK_MODE=full")
tests/plugins/LightDM/pam.cppnew file+51
@@ -0,0 +1,51 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "GreeterPrivate.h"
18+
19+#include <QtTest>
20+
21+class GreeterPamTest : public QObject
22+{
23+ Q_OBJECT
24+
25+private Q_SLOTS:
26+
27+ void init()
28+ {
29+ m_greeterpriv = new QLightDM::GreeterPrivate();
30+ }
31+
32+ void cleanup()
33+ {
34+ delete m_greeterpriv;
35+ }
36+
37+ void testRapidFireAuthentication()
38+ {
39+ m_greeterpriv->authenticationUser = qgetenv("USER");
40+ for (int i = 0; i < 100; i++) {
41+ m_greeterpriv->handleAuthenticate();
42+ }
43+ }
44+
45+private:
46+ QLightDM::GreeterPrivate *m_greeterpriv;
47+};
48+
49+QTEST_MAIN(GreeterPamTest)
50+
51+#include "pam.moc"