Skip to content

Fix #13852 (GUI does not finish analysis properly) #7633

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 35 additions & 25 deletions gui/threadhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@

ThreadHandler::ThreadHandler(QObject *parent) :
QObject(parent)
{
setThreadCount(1);
}
{}

ThreadHandler::~ThreadHandler()
{
Expand All @@ -54,7 +52,7 @@ void ThreadHandler::clearFiles()
mAnalyseWholeProgram = false;
mCtuInfo.clear();
mAddonsAndTools.clear();
mSuppressions.clear();
mSuppressionsUI.clear();
}

void ThreadHandler::setFiles(const QStringList &files)
Expand Down Expand Up @@ -83,6 +81,14 @@ void ThreadHandler::setCheckFiles(const QStringList& files)
}
}

void ThreadHandler::setupCheckThread(CheckThread &thread) const
{
thread.setAddonsAndTools(mCheckAddonsAndTools);
thread.setSuppressions(mSuppressionsUI);
thread.setClangIncludePaths(mClangIncludePaths);
thread.setSettings(mCheckSettings, mCheckSuppressions);
}

void ThreadHandler::check(const Settings &settings, const std::shared_ptr<Suppressions>& supprs)
{
if (mResults.getFileCount() == 0 || mRunningThreadCount > 0 || settings.jobs == 0) {
Expand All @@ -91,25 +97,25 @@ void ThreadHandler::check(const Settings &settings, const std::shared_ptr<Suppre
return;
}

setThreadCount(settings.jobs);
mCheckSettings = settings;
mCheckSuppressions = supprs;

createThreads(mCheckSettings.jobs);

mRunningThreadCount = mThreads.size();
mRunningThreadCount = std::min(mResults.getFileCount(), mRunningThreadCount);

QStringList addonsAndTools = mAddonsAndTools;
for (const std::string& addon: settings.addons) {
mCheckAddonsAndTools = mAddonsAndTools;
for (const std::string& addon: mCheckSettings.addons) {
QString s = QString::fromStdString(addon);
if (!addonsAndTools.contains(s))
addonsAndTools << s;
if (!mCheckAddonsAndTools.contains(s))
mCheckAddonsAndTools << s;
}

mCtuInfo.clear();

for (int i = 0; i < mRunningThreadCount; i++) {
mThreads[i]->setAddonsAndTools(addonsAndTools);
mThreads[i]->setSuppressions(mSuppressions);
mThreads[i]->setClangIncludePaths(mClangIncludePaths);
mThreads[i]->setSettings(settings, supprs);
setupCheckThread(*mThreads[i]);
mThreads[i]->start();
}

Expand All @@ -123,14 +129,12 @@ void ThreadHandler::check(const Settings &settings, const std::shared_ptr<Suppre

bool ThreadHandler::isChecking() const
{
return mRunningThreadCount > 0;
return mRunningThreadCount > 0 || mAnalyseWholeProgram;
}

void ThreadHandler::setThreadCount(const int count)
void ThreadHandler::createThreads(const int count)
{
if (mRunningThreadCount > 0 ||
count == mThreads.size() ||
count <= 0) {
if (mRunningThreadCount > 0 || count <= 0) {
return;
}

Expand All @@ -140,9 +144,9 @@ void ThreadHandler::setThreadCount(const int count)
for (int i = mThreads.size(); i < count; i++) {
mThreads << new CheckThread(mResults);
connect(mThreads.last(), &CheckThread::done,
this, &ThreadHandler::threadDone);
this, &ThreadHandler::threadDone, Qt::QueuedConnection);
connect(mThreads.last(), &CheckThread::fileChecked,
&mResults, &ThreadResult::fileChecked);
&mResults, &ThreadResult::fileChecked, Qt::QueuedConnection);
}
}

Expand All @@ -151,7 +155,7 @@ void ThreadHandler::removeThreads()
{
for (CheckThread* thread : mThreads) {
if (thread->isRunning()) {
thread->terminate();
thread->stop();
thread->wait();
}
disconnect(thread, &CheckThread::done,
Expand All @@ -162,19 +166,22 @@ void ThreadHandler::removeThreads()
}

mThreads.clear();
mAnalyseWholeProgram = false;
}

void ThreadHandler::threadDone()
{
if (mRunningThreadCount == 1 && mAnalyseWholeProgram) {
mRunningThreadCount--;

if (mRunningThreadCount == 0 && mAnalyseWholeProgram) {
createThreads(1);
mRunningThreadCount = 1;
setupCheckThread(*mThreads[0]);
mThreads[0]->analyseWholeProgram(mLastFiles, mCtuInfo);
mAnalyseWholeProgram = false;
mCtuInfo.clear();
return;
}

mRunningThreadCount--;
if (mRunningThreadCount == 0) {
emit done();

Expand All @@ -185,6 +192,9 @@ void ThreadHandler::threadDone()
mLastCheckTime = mCheckStartTime;
mCheckStartTime = QDateTime();
}

mCheckAddonsAndTools.clear();
mCheckSuppressions.reset();
}
}

Expand Down Expand Up @@ -215,7 +225,7 @@ void ThreadHandler::initialize(const ResultsView *view)

void ThreadHandler::loadSettings(const QSettings &settings)
{
setThreadCount(settings.value(SETTINGS_CHECK_THREADS, 1).toInt());
createThreads(settings.value(SETTINGS_CHECK_THREADS, 1).toInt());
}

void ThreadHandler::saveSettings(QSettings &settings) const
Expand Down
36 changes: 27 additions & 9 deletions gui/threadhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#ifndef THREADHANDLER_H
#define THREADHANDLER_H

#include "settings.h"
#include "suppressions.h"
#include "threadresult.h"

Expand All @@ -37,7 +38,6 @@
class ResultsView;
class CheckThread;
class QSettings;
class Settings;
class ImportProject;
class ErrorItem;

Expand All @@ -55,12 +55,6 @@ class ThreadHandler : public QObject {
explicit ThreadHandler(QObject *parent = nullptr);
~ThreadHandler() override;

/**
* @brief Set the number of threads to use
* @param count The number of threads to use
*/
void setThreadCount(int count);

/**
* @brief Initialize the threads (connect all signals to resultsview's slots)
*
Expand All @@ -85,7 +79,7 @@ class ThreadHandler : public QObject {
}

void setSuppressions(const QList<SuppressionList::Suppression> &s) {
mSuppressions = s;
mSuppressionsUI = s;
}

void setClangIncludePaths(const QStringList &s) {
Expand Down Expand Up @@ -235,12 +229,24 @@ protected slots:
*/
int mScanDuration{};

/**
* @brief Create checker threads
* @param count The number of threads to spawn
*/
void createThreads(int count);

/**
* @brief Function to delete all threads
*
*/
void removeThreads();

/*
* @brief Apply check settings to a checker thread
* @param thread The thread to setup
*/
void setupCheckThread(CheckThread &thread) const;

/**
* @brief Thread results are stored here
*
Expand All @@ -259,12 +265,24 @@ protected slots:
*/
int mRunningThreadCount{};

/**
* @brief A whole program check is queued by check()
*/
bool mAnalyseWholeProgram{};
std::string mCtuInfo;

QStringList mAddonsAndTools;
QList<SuppressionList::Suppression> mSuppressions;
QList<SuppressionList::Suppression> mSuppressionsUI;
QStringList mClangIncludePaths;

/// @{
/**
* @brief Settings specific to the current analysis
*/
QStringList mCheckAddonsAndTools;
Settings mCheckSettings;
std::shared_ptr<Suppressions> mCheckSuppressions;
/// @}
private:

/**
Expand Down
Loading