diff --git a/NEWS.md b/NEWS.md index 8e98064e..59e6c7b1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -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 diff --git a/RedPandaIDE/compiler/compilermanager.cpp b/RedPandaIDE/compiler/compilermanager.cpp index 3eaffe99..bcd890de 100644 --- a/RedPandaIDE/compiler/compilermanager.cpp +++ b/RedPandaIDE/compiler/compilermanager.cpp @@ -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) diff --git a/RedPandaIDE/compiler/compilermanager.h b/RedPandaIDE/compiler/compilermanager.h index 776160cb..d669412b 100644 --- a/RedPandaIDE/compiler/compilermanager.h +++ b/RedPandaIDE/compiler/compilermanager.h @@ -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 problemCases); void stopRun(); + void stopPausing(); void stopCompile(); void stopCheckSyntax(); bool canCompile(const QString& filename); diff --git a/RedPandaIDE/compiler/executablerunner.cpp b/RedPandaIDE/compiler/executablerunner.cpp index 71071f19..73d276b0 100644 --- a/RedPandaIDE/compiler/executablerunner.cpp +++ b/RedPandaIDE/compiler/executablerunner.cpp @@ -1,6 +1,5 @@ #include "executablerunner.h" -#include #include #include #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(); + 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:"<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 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; +// } +// } + } +} diff --git a/RedPandaIDE/compiler/executablerunner.h b/RedPandaIDE/compiler/executablerunner.h index b408ed80..d0491092 100644 --- a/RedPandaIDE/compiler/executablerunner.h +++ b/RedPandaIDE/compiler/executablerunner.h @@ -2,6 +2,7 @@ #define EXECUTABLERUNNER_H #include "runner.h" +#include class ExecutableRunner : public Runner { @@ -23,10 +24,15 @@ private: QString mRedirectInputFilename; bool mRedirectInput; bool mStartConsole; + std::shared_ptr mProcess; // QThread interface protected: void run() override; + + // Runner interface +protected: + void doStop() override; }; #endif // EXECUTABLERUNNER_H diff --git a/RedPandaIDE/compiler/ojproblemcasesrunner.cpp b/RedPandaIDE/compiler/ojproblemcasesrunner.cpp index 65b6aa18..9c59c1bd 100644 --- a/RedPandaIDE/compiler/ojproblemcasesrunner.cpp +++ b/RedPandaIDE/compiler/ojproblemcasesrunner.cpp @@ -5,6 +5,7 @@ #include "../widgets/ojproblemsetmodel.h" #include + OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir, const QVector& problemCases, QObject *parent): Runner(filename,arguments,workDir,parent) diff --git a/RedPandaIDE/compiler/ojproblemcasesrunner.h b/RedPandaIDE/compiler/ojproblemcasesrunner.h index 114e93c5..8b59007e 100644 --- a/RedPandaIDE/compiler/ojproblemcasesrunner.h +++ b/RedPandaIDE/compiler/ojproblemcasesrunner.h @@ -25,6 +25,7 @@ private: // QThread interface protected: void run() override; + }; #endif // OJPROBLEMCASESRUNNER_H diff --git a/RedPandaIDE/compiler/runner.cpp b/RedPandaIDE/compiler/runner.cpp index af095a7f..877f3b24 100644 --- a/RedPandaIDE/compiler/runner.cpp +++ b/RedPandaIDE/compiler/runner.cpp @@ -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; } diff --git a/RedPandaIDE/compiler/runner.h b/RedPandaIDE/compiler/runner.h index 19525914..48ce4b56 100644 --- a/RedPandaIDE/compiler/runner.h +++ b/RedPandaIDE/compiler/runner.h @@ -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; diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 642f69cb..078d5ae7 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -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); diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 74529d96..27963147 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -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); diff --git a/tools/ConsolePauser/ConsolePauser.dev b/tools/ConsolePauser/ConsolePauser.dev index ba086be3..c182a345 100644 --- a/tools/ConsolePauser/ConsolePauser.dev +++ b/tools/ConsolePauser/ConsolePauser.dev @@ -28,7 +28,7 @@ CustomMakefile = IncludeVersionInfo = 0 SupportXPThemes = 0 CompilerSet = 0 -CompilerSettings = 000000a000110000000001000 +CompilerSettings = 000000a000000000000010001 UnitCount = 1 UsePrecompiledHeader = 0 PrecompiledHeader = diff --git a/tools/ConsolePauser/main.cpp b/tools/ConsolePauser/main.cpp index 5ff6ac01..4fbc5b8d 100644 --- a/tools/ConsolePauser/main.cpp +++ b/tools/ConsolePauser/main.cpp @@ -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--------------------------------");