summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarek Kobus <jaroslaw.kobus@qt.io>2022-07-21 17:48:49 +0200
committerJarek Kobus <jaroslaw.kobus@qt.io>2022-07-26 11:15:58 +0000
commitf6b37328c75649b106057a962d09dcb7fb2d3aa2 (patch)
tree7fb8c18e20835f8a247082f126617d5746ff2a8f
parent10da5083fe22d987b49b720be8cd5a5a69f17e9e (diff)
downloadqt-creator-f6b37328c75649b106057a962d09dcb7fb2d3aa2.tar.gz
AutotoolsBuildSystem: Avoid using sender()
According to the old explanation inside makefileParsingFinished() the solution of using sender() can't work reliably in this case. In scenarion where the old, deleted m_makefileParserThread had the same address as newly allocated one we might not detect correctly posted finished() signal of the deleted object. According to QObject::sender() documentation: "The pointer returned by this function becomes invalid if the sender is destroyed", so we can't rely on its value. Instead, add a new done() signal to the MakefileParserThread, which is being emitted from MakefileParserThread thread (i.e. from the thread where MakefileParserThread object lives in). In this way the finished() signal is still posted to the caller's thread, but this time if the MakefileParserThread object is already deleted, the finished() signal will be gone together with the MakefileParserThread object itself, so we also won't receive done() signal anymore. Simplify the internals by using std::unique_ptr. Change-Id: I43be209ecb71539ddefd72e50e9d60bfb43c49cb Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Eike Ziller <eike.ziller@qt.io>
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp45
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.h4
-rw-r--r--src/plugins/autotoolsprojectmanager/makefileparserthread.cpp4
-rw-r--r--src/plugins/autotoolsprojectmanager/makefileparserthread.h7
4 files changed, 23 insertions, 37 deletions
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp
index f7e27b8b60..c4ab94f585 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp
+++ b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp
@@ -55,53 +55,31 @@ AutotoolsBuildSystem::~AutotoolsBuildSystem()
{
delete m_cppCodeModelUpdater;
- if (m_makefileParserThread) {
+ if (m_makefileParserThread)
m_makefileParserThread->wait();
- delete m_makefileParserThread;
- m_makefileParserThread = nullptr;
- }
}
void AutotoolsBuildSystem::triggerParsing()
{
- if (m_makefileParserThread) {
- // The thread is still busy parsing a previous configuration.
- // Wait until the thread has been finished and delete it.
- // TODO: Discuss whether blocking is acceptable.
- disconnect(m_makefileParserThread,
- &QThread::finished,
- this,
- &AutotoolsBuildSystem::makefileParsingFinished);
+ // The thread is still busy parsing a previous configuration.
+ // Wait until the thread has been finished and delete it.
+ // TODO: Discuss whether blocking is acceptable.
+ if (m_makefileParserThread)
m_makefileParserThread->wait();
- delete m_makefileParserThread;
- m_makefileParserThread = nullptr;
- }
// Parse the makefile asynchronously in a thread
- m_makefileParserThread = new MakefileParserThread(this);
+ m_makefileParserThread.reset(new MakefileParserThread(this));
- connect(m_makefileParserThread,
- &MakefileParserThread::finished,
- this,
- &AutotoolsBuildSystem::makefileParsingFinished);
+ connect(m_makefileParserThread.get(), &MakefileParserThread::done,
+ this, &AutotoolsBuildSystem::makefileParsingFinished);
m_makefileParserThread->start();
}
void AutotoolsBuildSystem::makefileParsingFinished()
{
- // The finished() signal is from a previous makefile-parser-thread
- // and can be skipped. This can happen, if the thread has emitted the
- // finished() signal during the execution of AutotoolsBuildSystem::loadProjectTree().
- // In this case the signal is in the message queue already and deleting
- // the thread of course does not remove the signal again.
- if (sender() != m_makefileParserThread)
- return;
-
+ // The parsing has been cancelled by the user. Don't show any project data at all.
if (m_makefileParserThread->isCanceled()) {
- // The parsing has been cancelled by the user. Don't show any
- // project data at all.
- m_makefileParserThread->deleteLater();
- m_makefileParserThread = nullptr;
+ m_makefileParserThread.release()->deleteLater();
return;
}
@@ -151,8 +129,7 @@ void AutotoolsBuildSystem::makefileParsingFinished()
updateCppCodeModel();
- m_makefileParserThread->deleteLater();
- m_makefileParserThread = nullptr;
+ m_makefileParserThread.release()->deleteLater();
emitBuildSystemUpdated();
}
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.h b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.h
index 09cd656b77..078e01e7ec 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.h
+++ b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.h
@@ -29,6 +29,8 @@
#include <projectexplorer/buildsystem.h>
+#include <memory>
+
namespace CppEditor { class CppProjectUpdater; }
namespace AutotoolsProjectManager {
@@ -63,7 +65,7 @@ private:
QStringList m_files;
/// Responsible for parsing the makefiles asynchronously in a thread
- MakefileParserThread *m_makefileParserThread = nullptr;
+ std::unique_ptr<MakefileParserThread> m_makefileParserThread;
CppEditor::CppProjectUpdater *m_cppCodeModelUpdater = nullptr;
};
diff --git a/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp b/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp
index 1a88febbf8..183e396aa1 100644
--- a/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp
+++ b/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp
@@ -35,8 +35,8 @@ MakefileParserThread::MakefileParserThread(ProjectExplorer::BuildSystem *bs)
: m_parser(bs->projectFilePath().toString()),
m_guard(bs->guardParsingRun())
{
- connect(&m_parser, &MakefileParser::status,
- this, &MakefileParserThread::status);
+ connect(&m_parser, &MakefileParser::status, this, &MakefileParserThread::status);
+ connect(this, &QThread::finished, this, &MakefileParserThread::done, Qt::QueuedConnection);
}
QStringList MakefileParserThread::sources() const
diff --git a/src/plugins/autotoolsprojectmanager/makefileparserthread.h b/src/plugins/autotoolsprojectmanager/makefileparserthread.h
index 75547af1dc..cf2b448eeb 100644
--- a/src/plugins/autotoolsprojectmanager/makefileparserthread.h
+++ b/src/plugins/autotoolsprojectmanager/makefileparserthread.h
@@ -131,6 +131,13 @@ signals:
*/
void status(const QString &status);
+ /**
+ * Similar to finished, but emitted from MakefileParserThread thread, i.e. from the
+ * thread where the MakefileParserThread lives in, not the tread that it creates.
+ * This helps to avoid race condition when connecting to finished() signal.
+ */
+ void done();
+
private:
MakefileParser m_parser; ///< Is not accessible outside the thread