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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,10 +1,53 @@
#include "AsyncTask.h" #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() void AsyncTask::run()
{ {
runningMutex.lock();
running = true;
runTask(); runTask();
emit finished(); emit finished();
running = false;
runningMutex.unlock();
} }
AsyncTaskManager::AsyncTaskManager(QObject *parent) AsyncTaskManager::AsyncTaskManager(QObject *parent)
@ -19,5 +62,6 @@ AsyncTaskManager::~AsyncTaskManager()
void AsyncTaskManager::start(AsyncTask *task) void AsyncTaskManager::start(AsyncTask *task)
{ {
task->prepareRun();
threadPool->start(task); threadPool->start(task);
} }

View File

@ -4,18 +4,40 @@
#include <QRunnable> #include <QRunnable>
#include <QThreadPool> #include <QThreadPool>
#include <QMutex>
class AsyncTaskManager;
class AsyncTask : public QObject, public QRunnable class AsyncTask : public QObject, public QRunnable
{ {
Q_OBJECT Q_OBJECT
friend class AsyncTaskManager;
public: public:
AsyncTask(QObject *parent = nullptr);
~AsyncTask();
void run() override final; 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; virtual void runTask() =0;
signals: signals:
void finished(); void finished();
private:
bool running;
bool interrupted;
QMutex runningMutex;
void prepareRun();
}; };