From bdca23741b2c32eb57be0ef3acd192a9896c5c1b Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Mon, 2 Feb 2026 21:26:48 +0800 Subject: [PATCH 01/10] fix: store memoryUsed as long long instead of int --- src/base/LemonUtils.hpp | 7 +++++++ src/component/exportutil/exportutil.cpp | 4 ++-- src/core/contestant.cpp | 6 +++--- src/core/contestant.h | 6 +++--- src/core/judgingthread.cpp | 2 +- src/core/judgingthread.h | 4 ++-- src/core/taskjudger.cpp | 2 +- src/core/taskjudger.h | 2 +- src/detaildialog.cpp | 2 +- src/judgingdialog.cpp | 2 +- src/judgingdialog.h | 2 +- 11 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/base/LemonUtils.hpp b/src/base/LemonUtils.hpp index c4c60795..ac723fef 100644 --- a/src/base/LemonUtils.hpp +++ b/src/base/LemonUtils.hpp @@ -30,6 +30,13 @@ namespace Lemon::detail { } else return -1; } + inline int jsonReadHelper(long long &val, const QJsonValue &jval) { + if (jval.isDouble()) { + val = jval.toInteger(); + return 0; + } else + return -1; + } inline int jsonReadHelper(bool &val, const QJsonValue &jval) { if (jval.isBool()) { val = jval.toBool(); diff --git a/src/component/exportutil/exportutil.cpp b/src/component/exportutil/exportutil.cpp index ae27ff87..09c84d3f 100644 --- a/src/component/exportutil/exportutil.cpp +++ b/src/component/exportutil/exportutil.cpp @@ -126,7 +126,7 @@ auto ExportUtil::getContestantHtmlCode(Contest *contest, Contestant *contestant, QList> result = contestant->getResult(i); QList message = contestant->getMessage(i); QList> timeUsed = contestant->getTimeUsed(i); - QList> memoryUsed = contestant->getMemoryUsed(i); + QList> memoryUsed = contestant->getMemoryUsed(i); QList> score = contestant->getScore(i); for (int j = 0; j < inputFiles.size(); j++) { @@ -493,7 +493,7 @@ auto ExportUtil::getSmallerContestantHtmlCode(Contest *contest, Contestant *cont QList> result = contestant->getResult(i); QList message = contestant->getMessage(i); QList> timeUsed = contestant->getTimeUsed(i); - QList> memoryUsed = contestant->getMemoryUsed(i); + QList> memoryUsed = contestant->getMemoryUsed(i); QList> score = contestant->getScore(i); for (int j = 0; j < inputFiles.size(); j++) { diff --git a/src/core/contestant.cpp b/src/core/contestant.cpp index f9f0fb01..caa69209 100644 --- a/src/core/contestant.cpp +++ b/src/core/contestant.cpp @@ -36,7 +36,7 @@ auto Contestant::getScore(int index) const -> const QList> & { return auto Contestant::getTimeUsed(int index) const -> const QList> & { return timeUsed[index]; } -auto Contestant::getMemoryUsed(int index) const -> const QList> & { return memoryUsed[index]; } +auto Contestant::getMemoryUsed(int index) const -> const QList> & { return memoryUsed[index]; } auto Contestant::getJudingTime() const -> QDateTime { return judgingTime; } @@ -60,7 +60,7 @@ void Contestant::setScore(int index, const QList> &_score) { score[in void Contestant::setTimeUsed(int index, const QList> &_timeUsed) { timeUsed[index] = _timeUsed; } -void Contestant::setMemoryUsed(int index, const QList> &_memoryUsed) { +void Contestant::setMemoryUsed(int index, const QList> &_memoryUsed) { memoryUsed[index] = _memoryUsed; } @@ -76,7 +76,7 @@ void Contestant::addTask() { message.append(QList()); score.append(QList>()); timeUsed.append(QList>()); - memoryUsed.append(QList>()); + memoryUsed.append(QList>()); } void Contestant::deleteTask(int index) { diff --git a/src/core/contestant.h b/src/core/contestant.h index b9f693f7..9e06741b 100644 --- a/src/core/contestant.h +++ b/src/core/contestant.h @@ -30,7 +30,7 @@ class Contestant : public QObject { const QList &getMessage(int) const; const QList> &getScore(int) const; const QList> &getTimeUsed(int) const; - const QList> &getMemoryUsed(int) const; + const QList> &getMemoryUsed(int) const; QDateTime getJudingTime() const; int getTaskScore(int) const; int getTotalScore() const; @@ -46,7 +46,7 @@ class Contestant : public QObject { void setMessage(int, const QList &); void setScore(int, const QList> &); void setTimeUsed(int, const QList> &); - void setMemoryUsed(int, const QList> &); + void setMemoryUsed(int, const QList> &); void setJudgingTime(QDateTime); int writeToJson(QJsonObject &); @@ -64,7 +64,7 @@ class Contestant : public QObject { QList> message; QList>> score; QList>> timeUsed; - QList>> memoryUsed; + QList>> memoryUsed; QDateTime judgingTime; // QList taskResults; diff --git a/src/core/judgingthread.cpp b/src/core/judgingthread.cpp index 7eea30d6..abf3ed0b 100644 --- a/src/core/judgingthread.cpp +++ b/src/core/judgingthread.cpp @@ -99,7 +99,7 @@ void JudgingThread::setInterpreterAsWatcher(bool use) { interpreterAsWatcher = u auto JudgingThread::getTimeUsed() const -> int { return timeUsed; } -auto JudgingThread::getMemoryUsed() const -> int { return memoryUsed; } +auto JudgingThread::getMemoryUsed() const -> long long { return memoryUsed; } auto JudgingThread::getScore() const -> int { return score; } diff --git a/src/core/judgingthread.h b/src/core/judgingthread.h index ac3db817..cf6b74d8 100644 --- a/src/core/judgingthread.h +++ b/src/core/judgingthread.h @@ -39,7 +39,7 @@ class JudgingThread : public QThread { void setRawMemoryLimit(int); void setInterpreterAsWatcher(bool); int getTimeUsed() const; - int getMemoryUsed() const; + long long getMemoryUsed() const; int getScore() const; int getFullScore() const; int getJudgeTimes() const; @@ -70,7 +70,7 @@ class JudgingThread : public QThread { int memoryLimit{}; int rawMemoryLimit{}; int timeUsed; - int memoryUsed; + long long memoryUsed; int score{}; int judgedTimes; ResultState result; diff --git a/src/core/taskjudger.cpp b/src/core/taskjudger.cpp index e1038c63..756ac59b 100644 --- a/src/core/taskjudger.cpp +++ b/src/core/taskjudger.cpp @@ -361,7 +361,7 @@ int TaskJudger::judge() { for (int i = 0; i < task->getTestCaseList().size(); i++) { timeUsed.append(QList()); - memoryUsed.append(QList()); + memoryUsed.append(QList()); score.append(QList()); result.append(QList()); overallStatus.append(maxDependValue); diff --git a/src/core/taskjudger.h b/src/core/taskjudger.h index c7cd0db9..71e3b0e6 100644 --- a/src/core/taskjudger.h +++ b/src/core/taskjudger.h @@ -56,7 +56,7 @@ class TaskJudger : public QObject { QProcessEnvironment environment; QList overallStatus; QList> timeUsed; - QList> memoryUsed; + QList> memoryUsed; QList> score; QList> result; QList message; diff --git a/src/detaildialog.cpp b/src/detaildialog.cpp index 15533d96..d360196d 100644 --- a/src/detaildialog.cpp +++ b/src/detaildialog.cpp @@ -133,7 +133,7 @@ void DetailDialog::refreshViewer(Contest *_contest, Contestant *_contestant) { QList> result = contestant->getResult(i); QList message = contestant->getMessage(i); QList> timeUsed = contestant->getTimeUsed(i); - QList> memoryUsed = contestant->getMemoryUsed(i); + QList> memoryUsed = contestant->getMemoryUsed(i); QList> score = contestant->getScore(i); for (int j = 0; j < inputFiles.size(); j++) { diff --git a/src/judgingdialog.cpp b/src/judgingdialog.cpp index 710532e1..cf034755 100644 --- a/src/judgingdialog.cpp +++ b/src/judgingdialog.cpp @@ -85,7 +85,7 @@ void JudgingDialog::judgeAll() { } void JudgingDialog::singleCaseFinished(QString contestantName, int progress, int x, int y, int result, - int scoreGot, int timeUsed, int memoryUsed) { + int scoreGot, int timeUsed, long long memoryUsed) { bool isOnMaxValue = ui->logViewer->verticalScrollBar()->value() == ui->logViewer->verticalScrollBar()->maximum(); QTextBlockFormat blockFormat; diff --git a/src/judgingdialog.h b/src/judgingdialog.h index b5eee520..7594f87a 100644 --- a/src/judgingdialog.h +++ b/src/judgingdialog.h @@ -44,7 +44,7 @@ class JudgingDialog : public QDialog { public slots: void dialogAlert(const QString &); - void singleCaseFinished(QString, int, int, int, int, int, int, int); + void singleCaseFinished(QString, int, int, int, int, int, int, long long); void singleSubtaskDependenceFinished(int, int, int); void taskJudgingStarted(const QString &); void taskJudgedDisplay(const QString &, const QList> &, const int); From 5c254db69ec8958ba1f5f2e0fb7b5d5a742aee0a Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Mon, 2 Feb 2026 21:28:18 +0800 Subject: [PATCH 02/10] upd --- src/core/judgingthread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/judgingthread.cpp b/src/core/judgingthread.cpp index abf3ed0b..ce1ae939 100644 --- a/src/core/judgingthread.cpp +++ b/src/core/judgingthread.cpp @@ -924,7 +924,7 @@ void JudgingThread::runProgram() { if (memoryLimit != -1) { GetProcessMemoryInfo(pi.hProcess, (PROCESS_MEMORY_COUNTERS *)&memoryInfo, sizeof(memoryInfo)); - if (qMax(memoryInfo.PrivateUsage, memoryInfo.PeakWorkingSetSize) > memoryLimit * 1024 * 1024) { + if (qMax(memoryInfo.PrivateUsage, memoryInfo.PeakWorkingSetSize) > 1ll * memoryLimit * 1024 * 1024) { TerminateProcess(pi.hProcess, 0); score = 0; From 4104db54b524f5da873e7d63c97e929e323c4be8 Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Tue, 3 Feb 2026 14:24:02 +0800 Subject: [PATCH 03/10] fix --- src/base/LemonUtils.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/LemonUtils.hpp b/src/base/LemonUtils.hpp index ac723fef..50a99965 100644 --- a/src/base/LemonUtils.hpp +++ b/src/base/LemonUtils.hpp @@ -30,7 +30,7 @@ namespace Lemon::detail { } else return -1; } - inline int jsonReadHelper(long long &val, const QJsonValue &jval) { + inline long long jsonReadHelper(long long &val, const QJsonValue &jval) { if (jval.isDouble()) { val = jval.toInteger(); return 0; From 6d561eb00b407fbd8f71a731b2f67c44397e948a Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Tue, 3 Feb 2026 14:26:37 +0800 Subject: [PATCH 04/10] fmt --- src/core/contestant.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/contestant.cpp b/src/core/contestant.cpp index caa69209..55379b02 100644 --- a/src/core/contestant.cpp +++ b/src/core/contestant.cpp @@ -36,7 +36,9 @@ auto Contestant::getScore(int index) const -> const QList> & { return auto Contestant::getTimeUsed(int index) const -> const QList> & { return timeUsed[index]; } -auto Contestant::getMemoryUsed(int index) const -> const QList> & { return memoryUsed[index]; } +auto Contestant::getMemoryUsed(int index) const -> const QList> & { + return memoryUsed[index]; +} auto Contestant::getJudingTime() const -> QDateTime { return judgingTime; } From 2e6a4dfb102148196d05f6caeee222124e9ed691 Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Mon, 9 Feb 2026 11:44:45 +0800 Subject: [PATCH 05/10] use int64_t instead of long long --- src/base/LemonUtils.hpp | 2 +- src/component/exportutil/exportutil.cpp | 4 ++-- src/core/contestant.cpp | 6 +++--- src/core/contestant.h | 6 +++--- src/core/judgingthread.cpp | 2 +- src/core/judgingthread.h | 4 ++-- src/core/taskjudger.cpp | 2 +- src/core/taskjudger.h | 2 +- src/detaildialog.cpp | 2 +- src/judgingdialog.cpp | 2 +- src/judgingdialog.h | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/base/LemonUtils.hpp b/src/base/LemonUtils.hpp index 50a99965..eafb2f40 100644 --- a/src/base/LemonUtils.hpp +++ b/src/base/LemonUtils.hpp @@ -30,7 +30,7 @@ namespace Lemon::detail { } else return -1; } - inline long long jsonReadHelper(long long &val, const QJsonValue &jval) { + inline int64_t jsonReadHelper(int64_t &val, const QJsonValue &jval) { if (jval.isDouble()) { val = jval.toInteger(); return 0; diff --git a/src/component/exportutil/exportutil.cpp b/src/component/exportutil/exportutil.cpp index 09c84d3f..92056ed5 100644 --- a/src/component/exportutil/exportutil.cpp +++ b/src/component/exportutil/exportutil.cpp @@ -126,7 +126,7 @@ auto ExportUtil::getContestantHtmlCode(Contest *contest, Contestant *contestant, QList> result = contestant->getResult(i); QList message = contestant->getMessage(i); QList> timeUsed = contestant->getTimeUsed(i); - QList> memoryUsed = contestant->getMemoryUsed(i); + QList> memoryUsed = contestant->getMemoryUsed(i); QList> score = contestant->getScore(i); for (int j = 0; j < inputFiles.size(); j++) { @@ -493,7 +493,7 @@ auto ExportUtil::getSmallerContestantHtmlCode(Contest *contest, Contestant *cont QList> result = contestant->getResult(i); QList message = contestant->getMessage(i); QList> timeUsed = contestant->getTimeUsed(i); - QList> memoryUsed = contestant->getMemoryUsed(i); + QList> memoryUsed = contestant->getMemoryUsed(i); QList> score = contestant->getScore(i); for (int j = 0; j < inputFiles.size(); j++) { diff --git a/src/core/contestant.cpp b/src/core/contestant.cpp index 55379b02..4a842425 100644 --- a/src/core/contestant.cpp +++ b/src/core/contestant.cpp @@ -36,7 +36,7 @@ auto Contestant::getScore(int index) const -> const QList> & { return auto Contestant::getTimeUsed(int index) const -> const QList> & { return timeUsed[index]; } -auto Contestant::getMemoryUsed(int index) const -> const QList> & { +auto Contestant::getMemoryUsed(int index) const -> const QList> & { return memoryUsed[index]; } @@ -62,7 +62,7 @@ void Contestant::setScore(int index, const QList> &_score) { score[in void Contestant::setTimeUsed(int index, const QList> &_timeUsed) { timeUsed[index] = _timeUsed; } -void Contestant::setMemoryUsed(int index, const QList> &_memoryUsed) { +void Contestant::setMemoryUsed(int index, const QList> &_memoryUsed) { memoryUsed[index] = _memoryUsed; } @@ -78,7 +78,7 @@ void Contestant::addTask() { message.append(QList()); score.append(QList>()); timeUsed.append(QList>()); - memoryUsed.append(QList>()); + memoryUsed.append(QList>()); } void Contestant::deleteTask(int index) { diff --git a/src/core/contestant.h b/src/core/contestant.h index 9e06741b..a7c9c128 100644 --- a/src/core/contestant.h +++ b/src/core/contestant.h @@ -30,7 +30,7 @@ class Contestant : public QObject { const QList &getMessage(int) const; const QList> &getScore(int) const; const QList> &getTimeUsed(int) const; - const QList> &getMemoryUsed(int) const; + const QList> &getMemoryUsed(int) const; QDateTime getJudingTime() const; int getTaskScore(int) const; int getTotalScore() const; @@ -46,7 +46,7 @@ class Contestant : public QObject { void setMessage(int, const QList &); void setScore(int, const QList> &); void setTimeUsed(int, const QList> &); - void setMemoryUsed(int, const QList> &); + void setMemoryUsed(int, const QList> &); void setJudgingTime(QDateTime); int writeToJson(QJsonObject &); @@ -64,7 +64,7 @@ class Contestant : public QObject { QList> message; QList>> score; QList>> timeUsed; - QList>> memoryUsed; + QList>> memoryUsed; QDateTime judgingTime; // QList taskResults; diff --git a/src/core/judgingthread.cpp b/src/core/judgingthread.cpp index ce1ae939..20aedaa7 100644 --- a/src/core/judgingthread.cpp +++ b/src/core/judgingthread.cpp @@ -99,7 +99,7 @@ void JudgingThread::setInterpreterAsWatcher(bool use) { interpreterAsWatcher = u auto JudgingThread::getTimeUsed() const -> int { return timeUsed; } -auto JudgingThread::getMemoryUsed() const -> long long { return memoryUsed; } +auto JudgingThread::getMemoryUsed() const -> int64_t { return memoryUsed; } auto JudgingThread::getScore() const -> int { return score; } diff --git a/src/core/judgingthread.h b/src/core/judgingthread.h index cf6b74d8..38dba143 100644 --- a/src/core/judgingthread.h +++ b/src/core/judgingthread.h @@ -39,7 +39,7 @@ class JudgingThread : public QThread { void setRawMemoryLimit(int); void setInterpreterAsWatcher(bool); int getTimeUsed() const; - long long getMemoryUsed() const; + int64_t getMemoryUsed() const; int getScore() const; int getFullScore() const; int getJudgeTimes() const; @@ -70,7 +70,7 @@ class JudgingThread : public QThread { int memoryLimit{}; int rawMemoryLimit{}; int timeUsed; - long long memoryUsed; + int64_t memoryUsed; int score{}; int judgedTimes; ResultState result; diff --git a/src/core/taskjudger.cpp b/src/core/taskjudger.cpp index 756ac59b..dd088957 100644 --- a/src/core/taskjudger.cpp +++ b/src/core/taskjudger.cpp @@ -361,7 +361,7 @@ int TaskJudger::judge() { for (int i = 0; i < task->getTestCaseList().size(); i++) { timeUsed.append(QList()); - memoryUsed.append(QList()); + memoryUsed.append(QList()); score.append(QList()); result.append(QList()); overallStatus.append(maxDependValue); diff --git a/src/core/taskjudger.h b/src/core/taskjudger.h index 71e3b0e6..e5d89c64 100644 --- a/src/core/taskjudger.h +++ b/src/core/taskjudger.h @@ -56,7 +56,7 @@ class TaskJudger : public QObject { QProcessEnvironment environment; QList overallStatus; QList> timeUsed; - QList> memoryUsed; + QList> memoryUsed; QList> score; QList> result; QList message; diff --git a/src/detaildialog.cpp b/src/detaildialog.cpp index d360196d..b9a6c762 100644 --- a/src/detaildialog.cpp +++ b/src/detaildialog.cpp @@ -133,7 +133,7 @@ void DetailDialog::refreshViewer(Contest *_contest, Contestant *_contestant) { QList> result = contestant->getResult(i); QList message = contestant->getMessage(i); QList> timeUsed = contestant->getTimeUsed(i); - QList> memoryUsed = contestant->getMemoryUsed(i); + QList> memoryUsed = contestant->getMemoryUsed(i); QList> score = contestant->getScore(i); for (int j = 0; j < inputFiles.size(); j++) { diff --git a/src/judgingdialog.cpp b/src/judgingdialog.cpp index cf034755..4151002b 100644 --- a/src/judgingdialog.cpp +++ b/src/judgingdialog.cpp @@ -85,7 +85,7 @@ void JudgingDialog::judgeAll() { } void JudgingDialog::singleCaseFinished(QString contestantName, int progress, int x, int y, int result, - int scoreGot, int timeUsed, long long memoryUsed) { + int scoreGot, int timeUsed, int64_t memoryUsed) { bool isOnMaxValue = ui->logViewer->verticalScrollBar()->value() == ui->logViewer->verticalScrollBar()->maximum(); QTextBlockFormat blockFormat; diff --git a/src/judgingdialog.h b/src/judgingdialog.h index 7594f87a..c7120b65 100644 --- a/src/judgingdialog.h +++ b/src/judgingdialog.h @@ -44,7 +44,7 @@ class JudgingDialog : public QDialog { public slots: void dialogAlert(const QString &); - void singleCaseFinished(QString, int, int, int, int, int, int, long long); + void singleCaseFinished(QString, int, int, int, int, int, int, int64_t); void singleSubtaskDependenceFinished(int, int, int); void taskJudgingStarted(const QString &); void taskJudgedDisplay(const QString &, const QList> &, const int); From 7b47c7bc068ea50c2afe7e85153bd5121135ba76 Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Sun, 22 Mar 2026 09:17:31 +0800 Subject: [PATCH 06/10] use qint64 --- src/base/LemonUtils.hpp | 2 +- src/component/exportutil/exportutil.cpp | 4 ++-- src/core/contestant.cpp | 6 +++--- src/core/contestant.h | 6 +++--- src/core/judgingthread.cpp | 2 +- src/core/judgingthread.h | 4 ++-- src/core/taskjudger.cpp | 2 +- src/core/taskjudger.h | 2 +- src/detaildialog.cpp | 2 +- src/judgingdialog.cpp | 2 +- src/judgingdialog.h | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/base/LemonUtils.hpp b/src/base/LemonUtils.hpp index eafb2f40..67d2c195 100644 --- a/src/base/LemonUtils.hpp +++ b/src/base/LemonUtils.hpp @@ -30,7 +30,7 @@ namespace Lemon::detail { } else return -1; } - inline int64_t jsonReadHelper(int64_t &val, const QJsonValue &jval) { + inline qint64 jsonReadHelper(qint64 &val, const QJsonValue &jval) { if (jval.isDouble()) { val = jval.toInteger(); return 0; diff --git a/src/component/exportutil/exportutil.cpp b/src/component/exportutil/exportutil.cpp index 92056ed5..3cb35652 100644 --- a/src/component/exportutil/exportutil.cpp +++ b/src/component/exportutil/exportutil.cpp @@ -126,7 +126,7 @@ auto ExportUtil::getContestantHtmlCode(Contest *contest, Contestant *contestant, QList> result = contestant->getResult(i); QList message = contestant->getMessage(i); QList> timeUsed = contestant->getTimeUsed(i); - QList> memoryUsed = contestant->getMemoryUsed(i); + QList> memoryUsed = contestant->getMemoryUsed(i); QList> score = contestant->getScore(i); for (int j = 0; j < inputFiles.size(); j++) { @@ -493,7 +493,7 @@ auto ExportUtil::getSmallerContestantHtmlCode(Contest *contest, Contestant *cont QList> result = contestant->getResult(i); QList message = contestant->getMessage(i); QList> timeUsed = contestant->getTimeUsed(i); - QList> memoryUsed = contestant->getMemoryUsed(i); + QList> memoryUsed = contestant->getMemoryUsed(i); QList> score = contestant->getScore(i); for (int j = 0; j < inputFiles.size(); j++) { diff --git a/src/core/contestant.cpp b/src/core/contestant.cpp index 4a842425..5c4085d5 100644 --- a/src/core/contestant.cpp +++ b/src/core/contestant.cpp @@ -36,7 +36,7 @@ auto Contestant::getScore(int index) const -> const QList> & { return auto Contestant::getTimeUsed(int index) const -> const QList> & { return timeUsed[index]; } -auto Contestant::getMemoryUsed(int index) const -> const QList> & { +auto Contestant::getMemoryUsed(int index) const -> const QList> & { return memoryUsed[index]; } @@ -62,7 +62,7 @@ void Contestant::setScore(int index, const QList> &_score) { score[in void Contestant::setTimeUsed(int index, const QList> &_timeUsed) { timeUsed[index] = _timeUsed; } -void Contestant::setMemoryUsed(int index, const QList> &_memoryUsed) { +void Contestant::setMemoryUsed(int index, const QList> &_memoryUsed) { memoryUsed[index] = _memoryUsed; } @@ -78,7 +78,7 @@ void Contestant::addTask() { message.append(QList()); score.append(QList>()); timeUsed.append(QList>()); - memoryUsed.append(QList>()); + memoryUsed.append(QList>()); } void Contestant::deleteTask(int index) { diff --git a/src/core/contestant.h b/src/core/contestant.h index a7c9c128..2cd008ac 100644 --- a/src/core/contestant.h +++ b/src/core/contestant.h @@ -30,7 +30,7 @@ class Contestant : public QObject { const QList &getMessage(int) const; const QList> &getScore(int) const; const QList> &getTimeUsed(int) const; - const QList> &getMemoryUsed(int) const; + const QList> &getMemoryUsed(int) const; QDateTime getJudingTime() const; int getTaskScore(int) const; int getTotalScore() const; @@ -46,7 +46,7 @@ class Contestant : public QObject { void setMessage(int, const QList &); void setScore(int, const QList> &); void setTimeUsed(int, const QList> &); - void setMemoryUsed(int, const QList> &); + void setMemoryUsed(int, const QList> &); void setJudgingTime(QDateTime); int writeToJson(QJsonObject &); @@ -64,7 +64,7 @@ class Contestant : public QObject { QList> message; QList>> score; QList>> timeUsed; - QList>> memoryUsed; + QList>> memoryUsed; QDateTime judgingTime; // QList taskResults; diff --git a/src/core/judgingthread.cpp b/src/core/judgingthread.cpp index 20aedaa7..0a093f73 100644 --- a/src/core/judgingthread.cpp +++ b/src/core/judgingthread.cpp @@ -99,7 +99,7 @@ void JudgingThread::setInterpreterAsWatcher(bool use) { interpreterAsWatcher = u auto JudgingThread::getTimeUsed() const -> int { return timeUsed; } -auto JudgingThread::getMemoryUsed() const -> int64_t { return memoryUsed; } +auto JudgingThread::getMemoryUsed() const -> qint64 { return memoryUsed; } auto JudgingThread::getScore() const -> int { return score; } diff --git a/src/core/judgingthread.h b/src/core/judgingthread.h index 38dba143..e3cd0128 100644 --- a/src/core/judgingthread.h +++ b/src/core/judgingthread.h @@ -39,7 +39,7 @@ class JudgingThread : public QThread { void setRawMemoryLimit(int); void setInterpreterAsWatcher(bool); int getTimeUsed() const; - int64_t getMemoryUsed() const; + qint64 getMemoryUsed() const; int getScore() const; int getFullScore() const; int getJudgeTimes() const; @@ -70,7 +70,7 @@ class JudgingThread : public QThread { int memoryLimit{}; int rawMemoryLimit{}; int timeUsed; - int64_t memoryUsed; + qint64 memoryUsed; int score{}; int judgedTimes; ResultState result; diff --git a/src/core/taskjudger.cpp b/src/core/taskjudger.cpp index dd088957..944624cf 100644 --- a/src/core/taskjudger.cpp +++ b/src/core/taskjudger.cpp @@ -361,7 +361,7 @@ int TaskJudger::judge() { for (int i = 0; i < task->getTestCaseList().size(); i++) { timeUsed.append(QList()); - memoryUsed.append(QList()); + memoryUsed.append(QList()); score.append(QList()); result.append(QList()); overallStatus.append(maxDependValue); diff --git a/src/core/taskjudger.h b/src/core/taskjudger.h index e5d89c64..926cb090 100644 --- a/src/core/taskjudger.h +++ b/src/core/taskjudger.h @@ -56,7 +56,7 @@ class TaskJudger : public QObject { QProcessEnvironment environment; QList overallStatus; QList> timeUsed; - QList> memoryUsed; + QList> memoryUsed; QList> score; QList> result; QList message; diff --git a/src/detaildialog.cpp b/src/detaildialog.cpp index b9a6c762..e2d59d45 100644 --- a/src/detaildialog.cpp +++ b/src/detaildialog.cpp @@ -133,7 +133,7 @@ void DetailDialog::refreshViewer(Contest *_contest, Contestant *_contestant) { QList> result = contestant->getResult(i); QList message = contestant->getMessage(i); QList> timeUsed = contestant->getTimeUsed(i); - QList> memoryUsed = contestant->getMemoryUsed(i); + QList> memoryUsed = contestant->getMemoryUsed(i); QList> score = contestant->getScore(i); for (int j = 0; j < inputFiles.size(); j++) { diff --git a/src/judgingdialog.cpp b/src/judgingdialog.cpp index 4151002b..183cd52b 100644 --- a/src/judgingdialog.cpp +++ b/src/judgingdialog.cpp @@ -85,7 +85,7 @@ void JudgingDialog::judgeAll() { } void JudgingDialog::singleCaseFinished(QString contestantName, int progress, int x, int y, int result, - int scoreGot, int timeUsed, int64_t memoryUsed) { + int scoreGot, int timeUsed, qint64 memoryUsed) { bool isOnMaxValue = ui->logViewer->verticalScrollBar()->value() == ui->logViewer->verticalScrollBar()->maximum(); QTextBlockFormat blockFormat; diff --git a/src/judgingdialog.h b/src/judgingdialog.h index c7120b65..2f66c8ad 100644 --- a/src/judgingdialog.h +++ b/src/judgingdialog.h @@ -44,7 +44,7 @@ class JudgingDialog : public QDialog { public slots: void dialogAlert(const QString &); - void singleCaseFinished(QString, int, int, int, int, int, int, int64_t); + void singleCaseFinished(QString, int, int, int, int, int, int, qint64); void singleSubtaskDependenceFinished(int, int, int); void taskJudgingStarted(const QString &); void taskJudgedDisplay(const QString &, const QList> &, const int); From 5e4eeb1fbbb5ab4b1c8e05902f744853a1b951e2 Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Sun, 22 Mar 2026 09:23:05 +0800 Subject: [PATCH 07/10] merge --- src/core/judgingthread.cpp | 618 ++----------------------------------- 1 file changed, 25 insertions(+), 593 deletions(-) diff --git a/src/core/judgingthread.cpp b/src/core/judgingthread.cpp index 0a093f73..b19af4d3 100644 --- a/src/core/judgingthread.cpp +++ b/src/core/judgingthread.cpp @@ -11,7 +11,6 @@ #include "LemonType.hpp" #include "base/LemonLog.hpp" #include "base/settings.h" -#include "core/judgesharedvariables.h" #include "core/task.h" #include @@ -20,30 +19,14 @@ #include #include #include -#include #include #include -#include -#include #include #include #include #include -#ifdef Q_OS_WIN32 - -#include -// Don't change the include order -// psapi need type BOOL, which is included in windef.h -#include -#include -#include -#include -#include - -#endif - #define LEMON_MODULE_NAME "JudgingThread" JudgingThread::JudgingThread(QObject *parent) : QThread(parent) { @@ -688,580 +671,6 @@ void JudgingThread::testlibSpecialJudge(const QString &fileName) { result = CorrectAnswer; } -#ifdef Q_OS_WIN - -QString getRandomString(int length) { - static const QString possibleCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); - std::mt19937 gen(std::random_device{}()); - - std::uniform_int_distribution rand(0, possibleCharacters.length()); - QString randomString; - for (int i = 0; i < length; ++i) { - int index = rand(gen) % possibleCharacters.length(); - QChar nextChar = possibleCharacters.at(index); - randomString.append(nextChar); - } - return randomString; -} - -bool grantFileAccessPermissions(PSID appContainerSid, LPWSTR name, ACCESS_MASK accessMask) { - PACL oldAcl, newAcl = nullptr; - DWORD status; - EXPLICIT_ACCESSW ea; - do { - ea.grfAccessMode = GRANT_ACCESS; - ea.grfAccessPermissions = accessMask; - ea.grfInheritance = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; - ea.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - ea.Trustee.pMultipleTrustee = nullptr; - ea.Trustee.ptstrName = (PWSTR)appContainerSid; - ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; - status = GetNamedSecurityInfoW(name, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, - &oldAcl, nullptr, nullptr); - if (status != ERROR_SUCCESS) { - return false; - } - if (SetEntriesInAclW(1, &ea, oldAcl, &newAcl) != ERROR_SUCCESS) { - return false; - } - status = SetNamedSecurityInfoW(name, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, - newAcl, nullptr); - if (status != ERROR_SUCCESS) { - break; - } - } while (false); - if (newAcl) { - LocalFree(newAcl); - } - return status == ERROR_SUCCESS; -} -#endif -void JudgingThread::runProgram() { - result = CorrectAnswer; - int extraTime = qCeil(qMax(2000, timeLimit * 2) * extraTimeRatio); - - if (skipEnabled) { - result = TimeLimitExceeded; - score = 0; - return; - } - -#ifdef Q_OS_WIN32 - SetErrorMode(SEM_NOGPFAULTERRORBOX); - STARTUPINFOEX siex; - PROCESS_INFORMATION pi; - SECURITY_ATTRIBUTES sa; - ZeroMemory(&siex, sizeof(siex)); - siex.StartupInfo.cb = sizeof(siex); - siex.StartupInfo.dwFlags = STARTF_USESTDHANDLES; - ZeroMemory(&pi, sizeof(pi)); - ZeroMemory(&sa, sizeof(sa)); - sa.bInheritHandle = TRUE; - - PSID appContainerSID{nullptr}; - QString appContainerName = "Lemonlime" + getRandomString(10); - -#ifdef WINDOWS_APPCONTAINER_SUPPORT - // Create Window App Container (Windows 8+) - - auto hResult = CreateAppContainerProfile((const WCHAR *)(appContainerName.utf16()), - (const WCHAR *)(appContainerName.utf16()), - (const WCHAR *)(appContainerName.utf16()), nullptr, 0, - &appContainerSID); // Without any Permissions - - if (hResult != S_OK) { - score = 0; - result = CannotStartProgram; - message = "Failed to create app container"; - WARN("Failed to create app container"); - switch (hResult) { - case E_ACCESSDENIED: - WARN("Possible error: Access Denied"); - break; - case HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS): - WARN("Possible error:", appContainerName, "Already Exists"); - break; - case E_INVALIDARG: - WARN("Possible error: Invalid Args, Please Report Bugs"); - break; - default: - WARN("Unknown error"); - } - return; - } - - auto cleanupContainer = qScopeGuard([&] { - FreeSid(appContainerSID); - DeleteAppContainerProfile((const WCHAR *)(appContainerName.utf16())); - }); - - SECURITY_CAPABILITIES sc; - ZeroMemory(&sc, sizeof(sc)); - - sc.AppContainerSid = appContainerSID; - - SIZE_T attributesSize; - - InitializeProcThreadAttributeList(nullptr, 3, 0, &attributesSize); - - auto attributesListBuffer = std::make_unique(attributesSize); - siex.lpAttributeList = reinterpret_cast(attributesListBuffer.get()); - - if (! InitializeProcThreadAttributeList(siex.lpAttributeList, 3, 0, &attributesSize)) { - score = 0; - result = CannotStartProgram; - message = "Internal error (See log for further information)"; - WARN("Failed to InitializeProcThreadAttributeList()"); - WARN("Last Error code:", GetLastError()); - return; - } - - // Make App Run in App Container - if (! UpdateProcThreadAttribute(siex.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, &sc, - sizeof(sc), nullptr, nullptr)) { - score = 0; - result = CannotStartProgram; - message = "Internal error (See log for further information)"; - WARN("Failed to UpdateProcThreadAttribute()"); - WARN("Unable to make app run in app container"); - WARN("Last Error code:", GetLastError()); - return; - } - - // Ban Child Processs - - DWORD childProcessAttribute = PROCESS_CREATION_CHILD_PROCESS_RESTRICTED; - - if (! UpdateProcThreadAttribute(siex.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY, - &childProcessAttribute, sizeof(childProcessAttribute), nullptr, - nullptr)) { - score = 0; - result = CannotStartProgram; - message = "Internal error (See log for further information)"; - WARN("Failed to UpdateProcThreadAttribute()"); - WARN("Unable to limit fork"); - WARN("Last Error code:", GetLastError()); - return; - } - - // Load dlls - // Todo: If there's too many files under the path it'll be very slow - for (auto f : environment.value("PATH").split(';')) { - grantFileAccessPermissions(appContainerSID, (WCHAR *)f.utf16(), - FILE_GENERIC_EXECUTE | FILE_GENERIC_READ); - } - - if (! task->getStandardInputCheck()) { - grantFileAccessPermissions(appContainerSID, - (WCHAR *)(workingDirectory + task->getInputFileName()).utf16(), - FILE_GENERIC_READ); - } - - if (! task->getStandardOutputCheck()) { - grantFileAccessPermissions(appContainerSID, (WCHAR *)(workingDirectory).utf16(), - FILE_GENERIC_READ | FILE_ADD_FILE); - grantFileAccessPermissions(appContainerSID, - (WCHAR *)(workingDirectory + task->getOutputFileName()).utf16(), - FILE_GENERIC_READ | FILE_GENERIC_WRITE); - } - -#endif - - if (task->getStandardInputCheck()) { - siex.StartupInfo.hStdInput = CreateFileW((const WCHAR *)(inputFile.utf16()), GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &sa, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - } - - if (task->getStandardOutputCheck()) { - siex.StartupInfo.hStdOutput = - CreateFileW((const WCHAR *)((workingDirectory + "_tmpout").utf16()), GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &sa, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); - } - - siex.StartupInfo.hStdError = - CreateFileW((const WCHAR *)((workingDirectory + "_tmperr").utf16()), GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &sa, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); - - auto closeStdIO = qScopeGuard([&] { - if (task->getStandardInputCheck()) - CloseHandle(siex.StartupInfo.hStdInput); - - if (task->getStandardOutputCheck()) - CloseHandle(siex.StartupInfo.hStdOutput); - - CloseHandle(siex.StartupInfo.hStdError); - }); - - QString environmentValues = environment.toStringList().join(QChar('\0')) + '\0'; - - QString commandLine = QString(R"("%1" %2)").arg(executableFile).arg(arguments); - - if (! CreateProcessW(nullptr, (WCHAR *)(commandLine).utf16(), nullptr, &sa, TRUE, - HIGH_PRIORITY_CLASS | EXTENDED_STARTUPINFO_PRESENT | DETACHED_PROCESS, - (LPVOID)(environmentValues.toLocal8Bit().data()), - (const WCHAR *)(workingDirectory.utf16()), (STARTUPINFO *)(&siex), &pi)) { - score = 0; - result = CannotStartProgram; - message = "Failed to create process"; - WARN(executableFile, "Failed to be started"); - WARN("Last Error code:", GetLastError()); - return; - } - - auto closeProcessHandle = qScopeGuard([&] { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - }); - - PROCESS_MEMORY_COUNTERS_EX memoryInfo; - ZeroMemory(&memoryInfo, sizeof(memoryInfo)); - memoryInfo.cb = sizeof(memoryInfo); - - if (memoryLimit != -1) { - GetProcessMemoryInfo(pi.hProcess, (PROCESS_MEMORY_COUNTERS *)&memoryInfo, sizeof(memoryInfo)); - - if (qMax(memoryInfo.PrivateUsage, memoryInfo.PeakWorkingSetSize) > 1ll * memoryLimit * 1024 * 1024) { - TerminateProcess(pi.hProcess, 0); - - score = 0; - result = MemoryLimitExceeded; - memoryUsed = timeUsed = -1; - return; - } - } - - bool isProgramFinishedInExtraTimeLimit = false; - QElapsedTimer timer; - timer.start(); - - while (timer.elapsed() <= timeLimit + extraTime) { - if (WaitForSingleObject(pi.hProcess, 0) == WAIT_OBJECT_0) { - isProgramFinishedInExtraTimeLimit = true; - break; - } - - if (memoryLimit != -1) { - GetProcessMemoryInfo(pi.hProcess, (PROCESS_MEMORY_COUNTERS *)&memoryInfo, sizeof(memoryInfo)); - - if (qMax(memoryInfo.PrivateUsage, memoryInfo.PeakWorkingSetSize) > memoryLimit * 1024U * 1024) { - TerminateProcess(pi.hProcess, 0); - score = 0; - result = MemoryLimitExceeded; - memoryUsed = timeUsed = -1; - return; - } - } - - QCoreApplication::processEvents(); - - if (stopJudging || skipEnabled) { - TerminateProcess(pi.hProcess, 0); - - if (skipEnabled) { - score = 0; - result = TimeLimitExceeded; - timeUsed = memoryUsed = -1; - } - return; - } - - QThread::msleep(10); - } - - if (! isProgramFinishedInExtraTimeLimit) { - TerminateProcess(pi.hProcess, 0); - - score = 0; - result = TimeLimitExceeded; - timeUsed = -1; - return; - } - - unsigned long exitCode; - GetExitCodeProcess(pi.hProcess, &exitCode); - - if (exitCode != 0) { - - score = 0; - result = RunTimeError; - QFile file(workingDirectory + "_tmperr"); - - if (file.open(QFile::ReadOnly)) { - QTextStream stream(&file); - message = stream.readAll().right(1024); - file.close(); - } - - memoryUsed = timeUsed = -1; - LOG(executableFile, "Unexpectedly exited."); - LOG("Exit code", exitCode); - return; - } - - FILETIME creationTime, exitTime, kernelTime, userTime; - GetProcessTimes(pi.hProcess, &creationTime, &exitTime, &kernelTime, &userTime); - SYSTEMTIME realUserTime, realKernelTime; - FileTimeToSystemTime(&userTime, &realUserTime); - FileTimeToSystemTime(&kernelTime, &realKernelTime); - timeUsed = realUserTime.wMilliseconds + realUserTime.wSecond * 1000 + realUserTime.wMinute * 60 * 1000 + - realUserTime.wHour * 60 * 60 * 1000; - int kernelTimeUsed = realKernelTime.wMilliseconds + realKernelTime.wSecond * 1000 + - realKernelTime.wMinute * 60 * 1000 + realKernelTime.wHour * 60 * 60 * 1000; - GetProcessMemoryInfo(pi.hProcess, (PROCESS_MEMORY_COUNTERS *)&memoryInfo, sizeof(memoryInfo)); - memoryUsed = memoryInfo.PeakWorkingSetSize; - LOG(executableFile, "Successfully exited."); - LOG("User Time Used:", timeUsed, "ms, Kernel Time Used:", kernelTimeUsed, - "ms, User+Kernel Time Used:", timeUsed + kernelTimeUsed, "ms, Memory Used:", memoryUsed, "bytes"); -#else - -#ifdef Q_OS_LINUX - // TODO: rewrite with cgroup - QFile watcher(workingDirectory + QUuid::createUuid().toString(QUuid::Id128)); - - if (interpreterAsWatcher) { - QFile::copy(executableFile, watcher.fileName()); - } else { - QFile::copy(":/watcher/watcher_unix", watcher.fileName()); - } - - watcher.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner); - auto *runner = new QProcess(this); - QStringList argumentsList; - - argumentsList << "--dev" << "/dev"; - argumentsList << "--proc" << "/proc"; - argumentsList << "--ro-bind" << "/usr" << "/usr"; - argumentsList << "--symlink" << "/usr/lib" << "/lib"; - argumentsList << "--symlink" << "/usr/lib64" << "/lib64"; - argumentsList << "--symlink" << "/usr/bin" << "/bin"; - argumentsList << "--symlink" << "/usr/sbin" << "/sbin"; - argumentsList << "--tmpfs" << "/tmp"; - - argumentsList << "--unshare-all" << "--die-with-parent"; - - argumentsList << "--chdir" << workingDirectory; - - argumentsList << "--bind" << workingDirectory << workingDirectory; - - if (task->getStandardInputCheck()) { - argumentsList << "--ro-bind" << QFileInfo(inputFile).absoluteFilePath() - << QFileInfo(inputFile).absoluteFilePath(); - } - - argumentsList << watcher.fileName(); - - argumentsList << executableFile; - argumentsList << arguments; - - if (task->getStandardInputCheck()) { - argumentsList << QFileInfo(inputFile).absoluteFilePath(); - } else { - argumentsList << ""; - } - - if (task->getStandardOutputCheck()) { - argumentsList << "_tmpout"; - } else { - argumentsList << ""; - } - - argumentsList << "_tmperr"; - argumentsList << QString("%1").arg(timeLimit); - argumentsList << QString("%1").arg(memoryLimit); - argumentsList << QString("%1").arg(rawTimeLimit); - argumentsList << QString("%1").arg(rawMemoryLimit); - - if (task->getStandardInputCheck()) { - argumentsList << ""; - } else { - argumentsList << task->getInputFileName(); - } - - if (task->getStandardOutputCheck()) { - argumentsList << ""; - } else { - argumentsList << task->getOutputFileName(); - } - - qDebug() << argumentsList; - - QString bwrapPath = QStandardPaths::findExecutable("bwrap"); - if (bwrapPath.isEmpty()) { - score = 0; - result = CannotStartProgram; - message = tr("bwrap not found. Please install bubblewrap."); - return; - } - - runner->setProcessEnvironment(environment); - runner->setWorkingDirectory(workingDirectory); - runner->start(bwrapPath, argumentsList); - -#else - - QFile watcher(workingDirectory + QUuid::createUuid().toString(QUuid::Id128)); - - if (interpreterAsWatcher) { - QFile::copy(executableFile, watcher.fileName()); - } else { - QFile::copy(":/watcher/watcher_unix", watcher.fileName()); - } - - watcher.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner); - auto *runner = new QProcess(this); - QStringList argumentsList; - - argumentsList << executableFile; - argumentsList << arguments; - - if (task->getStandardInputCheck()) { - argumentsList << QFileInfo(inputFile).absoluteFilePath(); - } else { - argumentsList << ""; - } - - if (task->getStandardOutputCheck()) { - argumentsList << "_tmpout"; - } else { - argumentsList << ""; - } - - argumentsList << "_tmperr"; - argumentsList << QString("%1").arg(timeLimit); - argumentsList << QString("%1").arg(memoryLimit); - argumentsList << QString("%1").arg(rawTimeLimit); - argumentsList << QString("%1").arg(rawMemoryLimit); - - if (task->getStandardInputCheck()) { - argumentsList << ""; - } else { - argumentsList << task->getInputFileName(); - } - - if (task->getStandardOutputCheck()) { - argumentsList << ""; - } else { - argumentsList << task->getOutputFileName(); - } - - qDebug() << argumentsList; - - runner->setProcessEnvironment(environment); - runner->setWorkingDirectory(workingDirectory); - runner->start(watcher.fileName(), argumentsList); - -#endif - - if (! runner->waitForStarted(-1)) { - delete runner; - score = 0; - result = CannotStartProgram; - message = "Start runner failed"; - return; - } - - bool isProgramFinishedInExtraTimeLimit = false; - QElapsedTimer timer; - timer.start(); - - // Using rlimit to limit CPU time can only be accurate to seconds, - // so here it is rounded up to an integer second. - long long killTimeLimit = (timeLimit + 999) / 1000 * 1000 + extraTime; - while (timer.elapsed() <= killTimeLimit) { - if (runner->state() != QProcess::Running) { - isProgramFinishedInExtraTimeLimit = true; - break; - } - - QCoreApplication::processEvents(); - - if (stopJudging || skipEnabled) { - runner->terminate(); - runner->waitForFinished(-1); - delete runner; - - if (skipEnabled) { - score = 0; - result = TimeLimitExceeded; - timeUsed = memoryUsed = -1; - } - - return; - } - - msleep(10); - } - - if (! isProgramFinishedInExtraTimeLimit) { - runner->terminate(); - runner->waitForFinished(-1); - delete runner; - score = 0; - timeUsed = memoryUsed = -1; - // Watcher usually needs to handle the situation of program timeout and kill it. Therefore, it is - // abnormal for watcher to timeout itself, and report FAIL instead of TLE. - result = CannotStartProgram; - message = "Watcher time limit exceeded"; - return; - } - - { - QString out = QString::fromLocal8Bit(runner->readAllStandardOutput().constData()); - QTextStream stream(&out, QIODevice::ReadOnly); - stream >> timeUsed >> memoryUsed; - } - - message = QString::fromLocal8Bit(runner->readAllStandardError().constData()); - - enum : int { - RS_AC = 0, - RS_FAIL = 1, - RS_RE = 2, - RS_TLE = 3, - RS_MLE = 4, - }; - - int code = runner->exitCode(); - - switch (code) { - case RS_RE: - result = RunTimeError; - score = 0; - [[fallthrough]]; - case RS_AC: { - QFile file(workingDirectory + "_tmperr"); - if (file.open(QFile::ReadOnly)) { - message += file.readAll().right(1024); - file.close(); - } - } break; - case RS_FAIL: - result = CannotStartProgram; - score = 0; - break; - case RS_TLE: - result = TimeLimitExceeded; - score = 0; - break; - case RS_MLE: - result = MemoryLimitExceeded; - score = 0; - break; - default: - result = CannotStartProgram; - score = 0; - message = QString("Watcher reported an invalid result: %1").arg(code); - break; - } - - delete runner; -#endif -} - void JudgingThread::judgeOutput() { QString fileName; @@ -1328,7 +737,30 @@ void JudgingThread::judgeTraditionalTask() { QFile::remove(workingDirectory + "_tmperr"); }); - runProgram(); + ProcessRunnerConfig cfg; + cfg.executableFile = executableFile; + cfg.arguments = arguments; + cfg.workingDirectory = workingDirectory; + cfg.inputFile = inputFile; + cfg.environment = environment; + cfg.timeLimit = timeLimit; + cfg.rawTimeLimit = rawTimeLimit; + cfg.memoryLimit = memoryLimit; + cfg.rawMemoryLimit = rawMemoryLimit; + cfg.extraTimeRatio = extraTimeRatio; + cfg.standardInputCheck = task->getStandardInputCheck(); + cfg.standardOutputCheck = task->getStandardOutputCheck(); + cfg.inputFileName = task->getInputFileName(); + cfg.outputFileName = task->getOutputFileName(); + cfg.interpreterAsWatcher = interpreterAsWatcher; + + auto processRunner = ProcessRunner::create(cfg, stopJudging); + auto runResult = processRunner->run(); + result = runResult.result; + score = runResult.score; + timeUsed = runResult.timeUsed; + memoryUsed = runResult.memoryUsed; + message = runResult.message; if (timeUsed > timeLimit) { if (score > 0 && @@ -1396,4 +828,4 @@ void JudgingThread::run() { judgeAnswersOnlyTask(); break; } -} +} \ No newline at end of file From 0156c06fd66aaa9ff33936dc5566a2097feeedfb Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Sun, 22 Mar 2026 09:27:29 +0800 Subject: [PATCH 08/10] fmt --- src/core/contestant.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/contestant.cpp b/src/core/contestant.cpp index 5c4085d5..6268cf38 100644 --- a/src/core/contestant.cpp +++ b/src/core/contestant.cpp @@ -36,9 +36,7 @@ auto Contestant::getScore(int index) const -> const QList> & { return auto Contestant::getTimeUsed(int index) const -> const QList> & { return timeUsed[index]; } -auto Contestant::getMemoryUsed(int index) const -> const QList> & { - return memoryUsed[index]; -} +auto Contestant::getMemoryUsed(int index) const -> const QList> & { return memoryUsed[index]; } auto Contestant::getJudingTime() const -> QDateTime { return judgingTime; } From 74c45848353cc40f5b12ffcdd76175b75a856723 Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Sun, 22 Mar 2026 09:43:24 +0800 Subject: [PATCH 09/10] use unsigned 1024 --- src/core/processrunner_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/processrunner_win.cpp b/src/core/processrunner_win.cpp index a1090389..40d4412b 100644 --- a/src/core/processrunner_win.cpp +++ b/src/core/processrunner_win.cpp @@ -268,7 +268,7 @@ ProcessRunnerResult WinProcessRunner::run() { if (config.memoryLimit != -1) { GetProcessMemoryInfo(pi.hProcess, (PROCESS_MEMORY_COUNTERS *)&memoryInfo, sizeof(memoryInfo)); - if (qMax(memoryInfo.PrivateUsage, memoryInfo.PeakWorkingSetSize) > config.memoryLimit * 1024 * 1024) { + if (qMax(memoryInfo.PrivateUsage, memoryInfo.PeakWorkingSetSize) > config.memoryLimit * 1024U * 1024) { TerminateProcess(pi.hProcess, 0); res.score = 0; From 6cfcbc62e93ca7330e348816ff85cd491b6a84e0 Mon Sep 17 00:00:00 2001 From: ZnPdCo Date: Sun, 22 Mar 2026 09:47:39 +0800 Subject: [PATCH 10/10] use long long --- src/core/processrunner_win.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/processrunner_win.cpp b/src/core/processrunner_win.cpp index 40d4412b..35ee2907 100644 --- a/src/core/processrunner_win.cpp +++ b/src/core/processrunner_win.cpp @@ -268,7 +268,8 @@ ProcessRunnerResult WinProcessRunner::run() { if (config.memoryLimit != -1) { GetProcessMemoryInfo(pi.hProcess, (PROCESS_MEMORY_COUNTERS *)&memoryInfo, sizeof(memoryInfo)); - if (qMax(memoryInfo.PrivateUsage, memoryInfo.PeakWorkingSetSize) > config.memoryLimit * 1024U * 1024) { + if (qMax(memoryInfo.PrivateUsage, memoryInfo.PeakWorkingSetSize) > + 1ll * config.memoryLimit * 1024 * 1024) { TerminateProcess(pi.hProcess, 0); res.score = 0; @@ -292,7 +293,7 @@ ProcessRunnerResult WinProcessRunner::run() { GetProcessMemoryInfo(pi.hProcess, (PROCESS_MEMORY_COUNTERS *)&memoryInfo, sizeof(memoryInfo)); if (qMax(memoryInfo.PrivateUsage, memoryInfo.PeakWorkingSetSize) > - config.memoryLimit * 1024U * 1024) { + 1ll * config.memoryLimit * 1024 * 1024) { TerminateProcess(pi.hProcess, 0); res.score = 0; res.result = MemoryLimitExceeded;