Use AsyncTask for initial analysis

This commit is contained in:
Florian Märkl 2018-05-26 20:09:20 +02:00
parent 790dd4868e
commit 7117846b3e
8 changed files with 111 additions and 58 deletions

View File

@ -1,48 +1,43 @@
#include "Cutter.h"
#include "AnalThread.h"
#include "AnalTask.h"
#include "MainWindow.h"
#include "dialogs/OptionsDialog.h"
#include <QJsonArray>
#include <QDebug>
#include <QCheckBox>
AnalThread::AnalThread(OptionsDialog *parent) :
QThread(parent),
AnalTask::AnalTask(OptionsDialog *parent) :
AsyncTask(parent),
level(2),
main(nullptr),
interrupted(false)
main(nullptr)
{
}
AnalThread::~AnalThread()
AnalTask::~AnalTask()
{
if (isRunning()) {
quit();
wait();
}
}
void AnalThread::start(MainWindow *main, int level, QList<QString> advanced)
void AnalTask::setSettings(MainWindow *main, int level, QList<QString> advanced)
{
this->main = main;
this->level = level;
this->advanced = advanced;
this->main = main;
QThread::start();
}
void AnalThread::interruptAndWait()
void AnalTask::interrupt()
{
interrupted = true;
while (isRunning()) {
AsyncTask::interrupt();
r_cons_singleton()->breaked = true;
r_sys_usleep(10000);
}
}
// run() will be called when a thread starts
void AnalThread::run()
void AnalTask::interruptAndWait()
{
do {
interrupt();
} while(!wait(10));
}
void AnalTask::runTask()
{
const auto optionsDialog = dynamic_cast<OptionsDialog *>(parent());
const auto &ui = optionsDialog->ui;
@ -51,7 +46,7 @@ void AnalThread::run()
if (ui->entry_loadOffset->text().length() > 0)
binLoadAddr = Core()->math(ui->entry_loadOffset->text());
ut64 mapAddr = Core()->math(ui->entry_mapOffset->text()); // Where to map the file once loaded (-m)
interrupted = false;
emit updateProgress(tr("Loading binary..."));
// Set the CPU details (handle auto)
@ -83,7 +78,7 @@ void AnalThread::run()
if (!fileLoaded) {
// Something wrong happened, fallback to open dialog
emit openFileFailed();
interrupted = true;
AsyncTask::interrupt();
return;
}
}

View File

@ -1,31 +1,26 @@
#ifndef ANALTHREAD_H
#define ANALTHREAD_H
#include <QThread>
#include "utils/AsyncTask.h"
class CutterCore;
class MainWindow;
class OptionsDialog;
class AnalThread : public QThread
class AnalTask : public AsyncTask
{
Q_OBJECT
public:
explicit AnalThread(OptionsDialog *parent = nullptr);
~AnalThread();
void start(MainWindow *main, int level, QList<QString> advanced);
public:
explicit AnalTask(OptionsDialog *parent = nullptr);
~AnalTask();
void setSettings(MainWindow *main, int level, QList<QString> advanced);
void interrupt() override;
void interruptAndWait();
bool isInterrupted()
{
return interrupted;
}
protected:
void run();
using QThread::start;
void runTask();
signals:
void updateProgress(QString str);
@ -35,8 +30,6 @@ private:
int level;
QList<QString> advanced;
MainWindow *main;
bool interrupted;
};
#endif // ANALTHREAD_H

View File

@ -312,11 +312,9 @@ public:
~CutterCore();
static CutterCore *getInstance();
/* Getters */
RVA getOffset() const
{
return core_->offset;
}
AsyncTaskManager *getAsyncTaskManager() { return asyncTaskManager; }
RVA getOffset() const { return core_->offset; }
static QString sanitizeStringForCommand(QString s);
QString cmd(const QString &str);

View File

@ -107,7 +107,7 @@ SOURCES += \
utils/MdHighlighter.cpp \
dialogs/preferences/AsmOptionsWidget.cpp \
dialogs/NewFileDialog.cpp \
AnalThread.cpp \
AnalTask.cpp \
widgets/CommentsWidget.cpp \
widgets/ConsoleWidget.cpp \
widgets/Dashboard.cpp \
@ -183,7 +183,7 @@ HEADERS += \
utils/MdHighlighter.h \
dialogs/OptionsDialog.h \
dialogs/NewFileDialog.h \
AnalThread.h \
AnalTask.h \
widgets/CommentsWidget.h \
widgets/ConsoleWidget.h \
widgets/Dashboard.h \

View File

@ -10,7 +10,7 @@
OptionsDialog::OptionsDialog(MainWindow *main):
QDialog(0), // parent may not be main
analThread(this),
analTask(this),
main(main),
core(Core()),
defaultAnalLevel(1),
@ -61,7 +61,7 @@ OptionsDialog::OptionsDialog(MainWindow *main):
// Add this so the dialog resizes when widgets are shown/hidden
//this->layout()->setSizeConstraint(QLayout::SetFixedSize);
connect(&analThread, SIGNAL(finished()), this, SLOT(analysisFinished()));
connect(&analTask, SIGNAL(finished()), this, SLOT(analysisFinished()));
connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
ui->programLineEdit->setText(main->getFilename());
@ -170,9 +170,10 @@ void OptionsDialog::setupAndStartAnalysis(int level, QList<QString> advanced)
connect(&analTimer, SIGNAL(timeout()), this, SLOT(updateProgressTimer()));
// Threads stuff, connect signal/slot
connect(&analThread, &AnalThread::updateProgress, this, &OptionsDialog::updateProgress);
connect(&analThread, &AnalThread::openFileFailed, main, &MainWindow::openNewFileFailed);
analThread.start(main, level, advanced);
connect(&analTask, &AnalTask::updateProgress, this, &OptionsDialog::updateProgress);
connect(&analTask, &AnalTask::openFileFailed, main, &MainWindow::openNewFileFailed);
analTask.setSettings(main, level, advanced);
Core()->getAsyncTaskManager()->start(&analTask);
}
void OptionsDialog::updateProgressTimer()
@ -249,7 +250,7 @@ void OptionsDialog::on_okButton_clicked()
void OptionsDialog::analysisFinished()
{
if (analThread.isInterrupted()) {
if (analTask.isInterrupted()) {
updateProgress(tr("Analysis aborted."));
done(1);
return;
@ -264,8 +265,8 @@ void OptionsDialog::analysisFinished()
void OptionsDialog::closeEvent(QCloseEvent *event)
{
if (analThread.isRunning()) {
analThread.interruptAndWait();
if (analTask.isRunning()) {
analTask.interruptAndWait();
}
event->accept();
}

View File

@ -7,7 +7,7 @@
#include <QElapsedTimer>
#include <memory>
#include "Cutter.h"
#include "AnalThread.h"
#include "AnalTask.h"
#include "ui_OptionsDialog.h"
class MainWindow;
@ -46,7 +46,7 @@ protected:
void closeEvent(QCloseEvent *event) override;
private:
AnalThread analThread;
AnalTask analTask;
MainWindow *main;
CutterCore *core;
int defaultAnalLevel;

View File

@ -1,10 +1,53 @@
#include "AsyncTask.h"
AsyncTask::AsyncTask(QObject *parent)
: QObject(parent),
QRunnable()
{
setAutoDelete(false);
running = false;
}
AsyncTask::~AsyncTask()
{
wait();
}
void AsyncTask::wait()
{
runningMutex.lock();
runningMutex.unlock();
}
bool AsyncTask::wait(int timeout)
{
bool r = runningMutex.tryLock(timeout);
if (r) {
runningMutex.unlock();
}
return r;
}
void AsyncTask::interrupt()
{
interrupted = true;
}
void AsyncTask::prepareRun()
{
interrupted = false;
wait();
}
void AsyncTask::run()
{
runningMutex.lock();
running = true;
runTask();
emit finished();
running = false;
runningMutex.unlock();
}
AsyncTaskManager::AsyncTaskManager(QObject *parent)
@ -19,5 +62,6 @@ AsyncTaskManager::~AsyncTaskManager()
void AsyncTaskManager::start(AsyncTask *task)
{
task->prepareRun();
threadPool->start(task);
}

View File

@ -4,18 +4,40 @@
#include <QRunnable>
#include <QThreadPool>
#include <QMutex>
class AsyncTaskManager;
class AsyncTask : public QObject, public QRunnable
{
Q_OBJECT
friend class AsyncTaskManager;
public:
AsyncTask(QObject *parent = nullptr);
~AsyncTask();
void run() override final;
void wait();
bool wait(int timeout);
virtual void interrupt();
bool isInterrupted() { return interrupted; }
bool isRunning() { return running; }
protected:
virtual void runTask() =0;
signals:
void finished();
private:
bool running;
bool interrupted;
QMutex runningMutex;
void prepareRun();
};