- enhancement: enable run/debug/compile when console program finished but pausing.

This commit is contained in:
Roy Qu 2021-12-23 17:07:27 +08:00
parent a50c6af5de
commit b956dbbcab
13 changed files with 200 additions and 41 deletions

View File

@ -1,3 +1,6 @@
Version 0.12.0 For Dev-C++ 7 Beta
- enhancement: enable run/debug/compile when console program finished but pausing.
Version 0.11.5 For Dev-C++ 7 Beta
- fix: step into instruction and step over instruction not correctly disabled when cpu dialog is created
- enhancement: icons in all dialogs auto change size with fonts

View File

@ -42,7 +42,7 @@ bool CompilerManager::backgroundSyntaxChecking()
bool CompilerManager::running()
{
QMutexLocker locker(&mRunnerMutex);
return mRunner!=nullptr;
return (mRunner!=nullptr && !mRunner->pausing());
}
void CompilerManager::compile(const QString& filename, const QByteArray& encoding, bool rebuild, bool silent, bool onlyCheckSyntax)
@ -199,7 +199,7 @@ void CompilerManager::checkSyntax(const QString &filename, const QString &conten
void CompilerManager::run(const QString &filename, const QString &arguments, const QString &workDir)
{
QMutexLocker locker(&mRunnerMutex);
if (mRunner!=nullptr) {
if (mRunner!=nullptr && !mRunner->pausing()) {
return;
}
QString redirectInputFilename;
@ -234,7 +234,9 @@ void CompilerManager::run(const QString &filename, const QString &arguments, con
}
mRunner = execRunner;
connect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
connect(mRunner, &Runner::finished, mRunner ,&Runner::deleteLater);
connect(mRunner, &Runner::finished, pMainWindow ,&MainWindow::onRunFinished);
connect(mRunner, &Runner::pausingForFinish, pMainWindow ,&MainWindow::onRunPausingForFinish);
connect(mRunner, &Runner::runErrorOccurred, pMainWindow ,&MainWindow::onRunErrorOccured);
mRunner->start();
}
@ -249,6 +251,7 @@ void CompilerManager::runProblem(const QString &filename, const QString &argumen
OJProblemCasesRunner * execRunner = new OJProblemCasesRunner(filename,arguments,workDir,problemCase);
mRunner = execRunner;
connect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
connect(mRunner, &Runner::finished, mRunner ,&Runner::deleteLater);
connect(mRunner, &Runner::finished, pMainWindow ,&MainWindow::onRunProblemFinished);
connect(mRunner, &Runner::runErrorOccurred, pMainWindow ,&MainWindow::onRunErrorOccured);
connect(execRunner, &OJProblemCasesRunner::caseStarted, pMainWindow, &MainWindow::onOJProblemCaseStarted);
@ -276,8 +279,22 @@ void CompilerManager::runProblem(const QString &filename, const QString &argumen
void CompilerManager::stopRun()
{
QMutexLocker locker(&mRunnerMutex);
if (mRunner!=nullptr)
if (mRunner!=nullptr) {
mRunner->stop();
disconnect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
mRunner=nullptr;
}
}
void CompilerManager::stopPausing()
{
QMutexLocker locker(&mRunnerMutex);
if (mRunner!=nullptr && mRunner->pausing()) {
disconnect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
mRunner->stop();
disconnect(mRunner, &Runner::finished, this ,&CompilerManager::onRunnerTerminated);
mRunner=nullptr;
}
}
void CompilerManager::stopCompile()
@ -309,9 +326,7 @@ void CompilerManager::onCompileFinished()
void CompilerManager::onRunnerTerminated()
{
QMutexLocker locker(&mRunnerMutex);
Runner* p=mRunner;
mRunner=nullptr;
p->deleteLater();
}
void CompilerManager::onCompileIssue(PCompileIssue issue)

View File

@ -30,6 +30,7 @@ public:
void runProblem(const QString& filename, const QString& arguments, const QString& workDir, POJProblemCase problemCase);
void runProblem(const QString& filename, const QString& arguments, const QString& workDir, QVector<POJProblemCase> problemCases);
void stopRun();
void stopPausing();
void stopCompile();
void stopCheckSyntax();
bool canCompile(const QString& filename);

View File

@ -1,6 +1,5 @@
#include "executablerunner.h"
#include <QProcess>
#include <windows.h>
#include <QDebug>
#include "compilermanager.h"
@ -50,15 +49,17 @@ void ExecutableRunner::run()
{
emit started();
auto action = finally([this]{
mProcess.reset();
setPausing(false);
emit terminated();
});
QProcess process;
mStop = false;
bool errorOccurred = false;
process.setProgram(mFilename);
process.setArguments(QProcess::splitCommand(mArguments));
process.setWorkingDirectory(mWorkDir);
mProcess = std::make_shared<QProcess>();
mProcess->setProgram(mFilename);
mProcess->setArguments(QProcess::splitCommand(mArguments));
mProcess->setWorkingDirectory(mWorkDir);
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QString path = env.value("PATH");
QStringList pathAdded;
@ -74,8 +75,8 @@ void ExecutableRunner::run()
path = pathAdded.join(PATH_SEPARATOR);
}
env.insert("PATH",path);
process.setProcessEnvironment(env);
process.setCreateProcessArgumentsModifier([this](QProcess::CreateProcessArguments * args){
mProcess->setProcessEnvironment(env);
mProcess->setCreateProcessArgumentsModifier([this](QProcess::CreateProcessArguments * args){
if (mStartConsole) {
args->flags |= CREATE_NEW_CONSOLE;
args->flags &= ~CREATE_NO_WINDOW;
@ -84,56 +85,96 @@ void ExecutableRunner::run()
args->startupInfo -> dwFlags &= ~STARTF_USESTDHANDLES;
}
});
process.connect(
&process, &QProcess::errorOccurred,
[&](){
connect(
mProcess.get(), &QProcess::errorOccurred,
[&errorOccurred](){
errorOccurred= true;
});
// if (!redirectInput()) {
// process.closeWriteChannel();
// }
process.start();
process.waitForStarted(5000);
if (process.state()==QProcess::Running && redirectInput()) {
process.write(readFileToByteArray(redirectInputFilename()));
process.closeWriteChannel();
mProcess->start();
mProcess->waitForStarted(5000);
if (mProcess->state()==QProcess::Running && redirectInput()) {
mProcess->write(readFileToByteArray(redirectInputFilename()));
mProcess->closeWriteChannel();
}
HANDLE hSharedMemory=INVALID_HANDLE_VALUE;
int BUF_SIZE=1024;
char* pBuf=nullptr;
if (mStartConsole) {
hSharedMemory = CreateFileMappingA(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
100,
"RED_PANDA_IDE_CONSOLE_PAUSER20211223"
);
if (hSharedMemory != NULL)
{
pBuf = (char*) MapViewOfFile(hSharedMemory, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf) {
pBuf[0]=0;
}
}
}
while (true) {
process.waitForFinished(1000);
if (process.state()!=QProcess::Running) {
mProcess->waitForFinished(1000);
if (mProcess->state()!=QProcess::Running) {
break;
}
if (mStop) {
process.closeReadChannel(QProcess::StandardOutput);
process.closeReadChannel(QProcess::StandardError);
process.closeWriteChannel();
#ifdef Q_OS_WIN
if (!mStartConsole) {
process.terminate();
if (process.waitForFinished(1000)) {
break;
}
}
#else
process.terminate();
if (process.waitForFinished(1000)) {
qDebug()<<"??1";
mProcess->closeReadChannel(QProcess::StandardOutput);
mProcess->closeReadChannel(QProcess::StandardError);
mProcess->closeWriteChannel();
qDebug()<<"??2";
#ifdef Q_OS_WIN
qDebug()<<"??3";
mProcess->terminate();
qDebug()<<"??4";
if (mProcess->waitForFinished(1000)) {
break;
}
#endif
#else
process->terminate();
if (process->waitForFinished(1000)) {
break;
}
#endif
for (int i=0;i<10;i++) {
process.kill();
if (process.waitForFinished(100)) {
qDebug()<<"??5";
mProcess->kill();
qDebug()<<"??6";
if (mProcess->waitForFinished(500)) {
break;
}
}
break;
}
if (mStartConsole && !mPausing && pBuf) {
if (strncmp(pBuf,"FINISHED",sizeof("FINISHED"))==0) {
setPausing(true);
emit pausingForFinish();
}
}
if (errorOccurred)
break;
}
if (pBuf)
UnmapViewOfFile(pBuf);
if (hSharedMemory!=INVALID_HANDLE_VALUE)
CloseHandle(hSharedMemory);
if (errorOccurred) {
//qDebug()<<"process error:"<<process.error();
switch (process.error()) {
switch (mProcess->error()) {
case QProcess::FailedToStart:
emit runErrorOccurred(tr("The runner process '%1' failed to start.").arg(mFilename));
break;
@ -155,3 +196,38 @@ void ExecutableRunner::run()
}
}
}
void ExecutableRunner::doStop()
{
std::shared_ptr<QProcess> process = mProcess;
if (process) {
// qDebug()<<"??1";
// process->closeReadChannel(QProcess::StandardOutput);
// process->closeReadChannel(QProcess::StandardError);
// process->closeWriteChannel();
// qDebug()<<"??2";
// #ifdef Q_OS_WIN
// if (!mStartConsole) {
// qDebug()<<"??3";
// process->terminate();
// qDebug()<<"??4";
// if (process->waitForFinished(1000)) {
// return;
// }
// }
// #else
// process->terminate();
// if (process->waitForFinished(1000)) {
// break;
// }
// #endif
// for (int i=0;i<10;i++) {
// qDebug()<<"??5";
// process->kill();
// qDebug()<<"??6";
// if (process->waitForFinished(100)) {
// break;
// }
// }
}
}

View File

@ -2,6 +2,7 @@
#define EXECUTABLERUNNER_H
#include "runner.h"
#include <QProcess>
class ExecutableRunner : public Runner
{
@ -23,10 +24,15 @@ private:
QString mRedirectInputFilename;
bool mRedirectInput;
bool mStartConsole;
std::shared_ptr<QProcess> mProcess;
// QThread interface
protected:
void run() override;
// Runner interface
protected:
void doStop() override;
};
#endif // EXECUTABLERUNNER_H

View File

@ -5,6 +5,7 @@
#include "../widgets/ojproblemsetmodel.h"
#include <QProcess>
OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir,
const QVector<POJProblemCase>& problemCases, QObject *parent):
Runner(filename,arguments,workDir,parent)

View File

@ -25,6 +25,7 @@ private:
// QThread interface
protected:
void run() override;
};
#endif // OJPROBLEMCASESRUNNER_H

View File

@ -2,6 +2,7 @@
Runner::Runner(const QString &filename, const QString &arguments, const QString &workDir
,QObject *parent) : QThread(parent),
mPausing(false),
mStop(false),
mFilename(filename),
mArguments(arguments),
@ -13,5 +14,21 @@ Runner::Runner(const QString &filename, const QString &arguments, const QString
void Runner::stop()
{
mStop = true;
doStop();
}
void Runner::doStop()
{
}
bool Runner::pausing() const
{
return mPausing;
}
void Runner::setPausing(bool newCanFinish)
{
mPausing = newCanFinish;
}

View File

@ -9,15 +9,22 @@ class Runner : public QThread
public:
explicit Runner(const QString& filename, const QString& arguments, const QString& workDir, QObject *parent = nullptr);
bool pausing() const;
signals:
void started();
void terminated();
void runErrorOccurred(const QString& reason);
void pausingForFinish(); // finish but pausing
public slots:
void stop();
protected:
virtual void doStop();
void setPausing(bool newCanFinish);
protected:
bool mPausing;
bool mStop;
QString mFilename;
QString mArguments;

View File

@ -1312,6 +1312,7 @@ void MainWindow::checkSyntaxInBack(Editor *e)
bool MainWindow::compile(bool rebuild)
{
mCompilerManager->stopPausing();
CompileTarget target =getCompileTarget();
if (target == CompileTarget::Project) {
if (mProject->modified())
@ -1355,6 +1356,7 @@ bool MainWindow::compile(bool rebuild)
void MainWindow::runExecutable(const QString &exeName,const QString &filename,RunType runType)
{
mCompilerManager->stopPausing();
// Check if it exists
if (!fileExists(exeName)) {
if (ui->actionCompile_Run->isEnabled()) {
@ -1452,6 +1454,7 @@ void MainWindow::debug()
{
if (mCompilerManager->compiling())
return;
mCompilerManager->stopPausing();
Settings::PCompilerSet compilerSet = pSettings->compilerSets().defaultSet();
if (!compilerSet) {
QMessageBox::critical(pMainWindow,
@ -3910,6 +3913,11 @@ void MainWindow::onRunFinished()
updateAppTitle();
}
void MainWindow::onRunPausingForFinish()
{
updateCompileActions();
}
void MainWindow::onRunProblemFinished()
{
ui->pbProblemCases->setVisible(false);

View File

@ -172,6 +172,7 @@ public slots:
void onCompileErrorOccured(const QString& reason);
void onRunErrorOccured(const QString& reason);
void onRunFinished();
void onRunPausingForFinish();
void onRunProblemFinished();
void onOJProblemCaseStarted(const QString& id, int current, int total);
void onOJProblemCaseFinished(const QString& id, int current, int total);

View File

@ -28,7 +28,7 @@ CustomMakefile =
IncludeVersionInfo = 0
SupportXPThemes = 0
CompilerSet = 0
CompilerSettings = 000000a000110000000001000
CompilerSettings = 000000a000000000000010001
UnitCount = 1
UsePrecompiledHeader = 0
PrecompiledHeader =

View File

@ -180,6 +180,25 @@ int main(int argc, char** argv) {
} else {
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
}
HANDLE hSharedMemory=INVALID_HANDLE_VALUE;
int BUF_SIZE=1024;
char* pBuf=nullptr;
hSharedMemory = OpenFileMappingA(
FILE_MAP_ALL_ACCESS,
FALSE,
"RED_PANDA_IDE_CONSOLE_PAUSER20211223"
);
if (hSharedMemory != NULL)
{
pBuf = (char*) MapViewOfFile(hSharedMemory, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
} else {
printf("can't open shared memory!");
}
// Save starting timestamp
LONGLONG starttime = GetClockTick();
@ -190,6 +209,10 @@ int main(int argc, char** argv) {
// Get ending timestamp
LONGLONG endtime = GetClockTick();
double seconds = (endtime - starttime) / (double)GetClockFrequency();
if (pBuf) {
strcpy(pBuf,"FINISHED");
}
// Done? Print return value of executed program
printf("\n--------------------------------");