on xenial help sign in
Handle start() being called while we are processing events during a cancel() call
commit4dc3bec5cb72a51ef251133c0de4e05f30a4a85f authorMichael Terry <michael.terry@canonical.com> dateWed 22 Apr 2015, 20:56 (12 years ago) parentcd4845a
1 file changed+19−4
plugins/LightDM/liblightdm/GreeterPrivate.cpp+19−4
plugins/LightDM/liblightdm/GreeterPrivate.cpp+19−4
@@ -69,6 +69,13 @@ public:
6969 {
7070 // Clear out any existing PAM interactions first
7171 cancelPam();
72+ if (pamHandle != nullptr) {
73+ // While we were cancelling pam above, we processed Qt events.
74+ // Which may have allowed someone to call start() on us again.
75+ // In which case, we'll bail on our current start() call.
76+ // This isn't racy because it's all in the same thread.
77+ return;
78+ }
7279
7380 AppData *appData = new AppData();
7481 appData->impl = this;
@@ -244,13 +251,21 @@ private:
244251 void cancelPam()
245252 {
246253 if (pamHandle != nullptr) {
254+ QFuture<int> pamFuture = futureWatcher.future();
247255 pam_handle *handle = pamHandle;
248256 pamHandle = nullptr; // to disable normal finishPam() handling
249− futureWatcher.cancel();
250− while (!futureWatcher.isFinished()) {
251− QCoreApplication::processEvents(); // let signal/slot handling happen
252− respond(QString());
257+ pamFuture.cancel();
258+
259+ // Note the empty loop, we just want to clear the futures queue.
260+ // Any further prompts from the pam thread will be immediately
261+ // responded to/dismissed in handlePrompt().
262+ while (respond(QString()));
263+
264+ // Now let signal/slot handling happen so the thread can finish
265+ while (!pamFuture.isFinished()) {
266+ QCoreApplication::processEvents();
253267 }
268+
254269 pam_end(handle, PAM_CONV_ERR);
255270 }
256271 }