[extension] Fix shared projects
This commit is contained in:
parent
2dabb4f9bc
commit
47ee997fa7
38
extension/bwcontest/package-lock.json
generated
38
extension/bwcontest/package-lock.json
generated
@ -10,8 +10,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vscode/vsce": "^2.22.0",
|
"@vscode/vsce": "^2.22.0",
|
||||||
"axios": "^1.6.5",
|
"axios": "^1.6.5",
|
||||||
|
"contest-monitor-types": "file:../../shared/contest-monitor-types",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"isomorphic-git": "^1.25.3",
|
"isomorphic-git": "^1.25.3",
|
||||||
|
"submission-runner": "file:../../shared/submission-runner",
|
||||||
"tree-kill": "^1.2.2",
|
"tree-kill": "^1.2.2",
|
||||||
"url-join": "^5.0.0",
|
"url-join": "^5.0.0",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
@ -49,7 +51,33 @@
|
|||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "^1.84.0"
|
"vscode": "^1.85.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"../../shared/contest-monitor-types": {},
|
||||||
|
"../../shared/submission-runner": {
|
||||||
|
"dependencies": {
|
||||||
|
"fs-extra": "^11.2.0",
|
||||||
|
"tree-kill": "^1.2.2",
|
||||||
|
"typescript": "^5.4.2",
|
||||||
|
"zod": "^3.22.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/fs-extra": "^11.0.4",
|
||||||
|
"@types/node": "20.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"../../shared/submissionRunner": {
|
||||||
|
"extraneous": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fs-extra": "^11.2.0",
|
||||||
|
"tree-kill": "^1.2.2",
|
||||||
|
"typescript": "^5.4.2",
|
||||||
|
"zod": "^3.22.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/fs-extra": "^11.0.4",
|
||||||
|
"@types/node": "20.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aashutoshrathi/word-wrap": {
|
"node_modules/@aashutoshrathi/word-wrap": {
|
||||||
@ -2177,6 +2205,10 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/contest-monitor-types": {
|
||||||
|
"resolved": "../../shared/contest-monitor-types",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/core-util-is": {
|
"node_modules/core-util-is": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
@ -6096,6 +6128,10 @@
|
|||||||
"postcss": "^8.2.15"
|
"postcss": "^8.2.15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/submission-runner": {
|
||||||
|
"resolved": "../../shared/submission-runner",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/supports-color": {
|
"node_modules/supports-color": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"vscode:prepublish": "npm run compile",
|
"vscode:prepublish": "npm run compile",
|
||||||
|
"check": "tsc -noEmit",
|
||||||
"esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node",
|
"esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node",
|
||||||
"esbuild": "npm run esbuild-base -- --sourcemap",
|
"esbuild": "npm run esbuild-base -- --sourcemap",
|
||||||
"compile": "rollup -c && npm run esbuild-base -- --minify",
|
"compile": "rollup -c && npm run esbuild-base -- --minify",
|
||||||
@ -115,8 +116,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vscode/vsce": "^2.22.0",
|
"@vscode/vsce": "^2.22.0",
|
||||||
"axios": "^1.6.5",
|
"axios": "^1.6.5",
|
||||||
|
"contest-monitor-types": "file:../../shared/contest-monitor-types",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"isomorphic-git": "^1.25.3",
|
"isomorphic-git": "^1.25.3",
|
||||||
|
"submission-runner": "file:../../shared/submission-runner",
|
||||||
"tree-kill": "^1.2.2",
|
"tree-kill": "^1.2.2",
|
||||||
"url-join": "^5.0.0",
|
"url-join": "^5.0.0",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
|
@ -4,12 +4,12 @@ import { cloneAndOpenRepo } from './extension';
|
|||||||
import { BWPanel } from './problemPanel';
|
import { BWPanel } from './problemPanel';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
import outputPanelLog from './outputPanelLog';
|
import outputPanelLog from './outputPanelLog';
|
||||||
import {
|
import type {
|
||||||
ContestStateForExtension,
|
ContestStateForExtension,
|
||||||
ProblemNameForExtension,
|
ProblemNameForExtension,
|
||||||
SubmissionForExtension,
|
SubmissionForExtension,
|
||||||
SubmissionStateForExtension
|
SubmissionStateForExtension
|
||||||
} from './contestMonitor/contestMonitorSharedTypes';
|
} from 'contest-monitor-types/contestMonitorTypes';
|
||||||
import { TeamData } from './sharedTypes';
|
import { TeamData } from './sharedTypes';
|
||||||
import {
|
import {
|
||||||
ContestTeamState,
|
ContestTeamState,
|
||||||
|
@ -2,12 +2,12 @@ import * as vscode from 'vscode';
|
|||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
import outputPanelLog from '../outputPanelLog';
|
import outputPanelLog from '../outputPanelLog';
|
||||||
import { extensionSettings } from '../extension';
|
import { extensionSettings } from '../extension';
|
||||||
import {
|
import type {
|
||||||
ContestStateForExtension,
|
ContestStateForExtension,
|
||||||
ProblemNameForExtension,
|
ProblemNameForExtension,
|
||||||
FullStateForExtension,
|
FullStateForExtension,
|
||||||
SubmissionForExtension
|
SubmissionForExtension
|
||||||
} from '@extensionWeb/contestMonitorTypes.cjs';
|
} from 'contest-monitor-types/contestMonitorTypes';
|
||||||
import { LiteEvent } from '../utilities/LiteEvent';
|
import { LiteEvent } from '../utilities/LiteEvent';
|
||||||
|
|
||||||
export type ContestTeamState = {
|
export type ContestTeamState = {
|
||||||
|
@ -2,11 +2,11 @@ import * as vscode from 'vscode';
|
|||||||
import { getNonce } from './getNonce';
|
import { getNonce } from './getNonce';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
import { extensionSettings } from './extension';
|
import { extensionSettings } from './extension';
|
||||||
import { runJava } from '@submissionRunner/java.cjs';
|
import { runJava } from 'submission-runner/java.cjs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { submitProblem } from './submit';
|
import { submitProblem } from './submit';
|
||||||
import { runCSharp } from '@submissionRunner/csharp.cjs';
|
import { runCSharp } from 'submission-runner/csharp.cjs';
|
||||||
import { runCpp } from '@submissionRunner/cpp.cjs';
|
import { runCpp } from 'submission-runner/cpp.cjs';
|
||||||
import { TeamData } from './sharedTypes';
|
import { TeamData } from './sharedTypes';
|
||||||
import outputPanelLog from './outputPanelLog';
|
import outputPanelLog from './outputPanelLog';
|
||||||
import { recordInitialSubmission } from './contestMonitor/contestStateSyncManager';
|
import { recordInitialSubmission } from './contestMonitor/contestStateSyncManager';
|
||||||
|
@ -5,7 +5,7 @@ import path = require('path');
|
|||||||
import http from 'isomorphic-git/http/node';
|
import http from 'isomorphic-git/http/node';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
import outputPanelLog from './outputPanelLog';
|
import outputPanelLog from './outputPanelLog';
|
||||||
import { SubmissionForExtension } from './contestMonitor/contestMonitorSharedTypes';
|
import type { SubmissionForExtension } from 'contest-monitor-types/contestMonitorTypes';
|
||||||
|
|
||||||
export async function submitProblem(
|
export async function submitProblem(
|
||||||
sessionToken: string,
|
sessionToken: string,
|
||||||
|
@ -3,22 +3,15 @@
|
|||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"outDir": "out",
|
"outDir": "out",
|
||||||
"lib": ["ES2020"],
|
"lib": ["ES2020", "DOM"],
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"rootDir": "src",
|
"rootDir": "src",
|
||||||
"strict": true, /* enable all strict type-checking options */
|
"esModuleInterop": true,
|
||||||
|
"strict": true /* enable all strict type-checking options */
|
||||||
/* Additional Checks */
|
/* Additional Checks */
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
"paths": {
|
|
||||||
"@submissionRunner/*": ["../../shared/submissionRunner/*"],
|
|
||||||
"@extensionWeb/*": ["../../shared/extensionWeb/*"]
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"exclude": ["webviews"],
|
"exclude": ["webviews"]
|
||||||
"references": [
|
|
||||||
{ "path": "../../shared/submissionRunner" },
|
|
||||||
{ "path": "../../shared/extensionWeb" }
|
|
||||||
]
|
|
||||||
}
|
}
|
3
shared/contest-monitor-types/package.json
Normal file
3
shared/contest-monitor-types/package.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"name": "contest-monitor-types"
|
||||||
|
}
|
12
shared/contest-monitor-types/tsconfig.json
Normal file
12
shared/contest-monitor-types/tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"declaration": true,
|
||||||
|
"composite": true,
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"outDir": "./build",
|
||||||
|
"strict": true,
|
||||||
|
"target": "ESNext",
|
||||||
|
"moduleResolution": "Node"
|
||||||
|
},
|
||||||
|
"include": ["*.ts"]
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"target": "es2016",
|
|
||||||
"module": "commonjs",
|
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"outDir": "./build",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"strict": true,
|
|
||||||
},
|
|
||||||
"include": ["/**/*.cts"]
|
|
||||||
}
|
|
@ -1,2 +1 @@
|
|||||||
node_modules
|
node_modules
|
||||||
/build
|
|
148
shared/submission-runner/cpp.cts
Normal file
148
shared/submission-runner/cpp.cts
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import { join } from "path";
|
||||||
|
import { exec, spawn } from "child_process";
|
||||||
|
import * as util from "util";
|
||||||
|
import type {
|
||||||
|
IRunner,
|
||||||
|
IRunnerParams,
|
||||||
|
IRunnerReturn,
|
||||||
|
RunResult,
|
||||||
|
} from "./types.cjs";
|
||||||
|
import { timeoutSeconds } from "./settings.cjs";
|
||||||
|
import kill from "tree-kill";
|
||||||
|
import * as os from "os";
|
||||||
|
import * as fs from "fs-extra";
|
||||||
|
|
||||||
|
const execPromise = util.promisify(exec);
|
||||||
|
|
||||||
|
export type CppPlatform = "VisualStudio" | "GCC";
|
||||||
|
|
||||||
|
interface IRunnerParamsCpp extends IRunnerParams {
|
||||||
|
srcDir: string;
|
||||||
|
problemName: string;
|
||||||
|
input: string;
|
||||||
|
cppPlatform: CppPlatform;
|
||||||
|
outputCallback?: (data: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const runCpp: IRunner<IRunnerParamsCpp> = async function (
|
||||||
|
params: IRunnerParamsCpp
|
||||||
|
): Promise<IRunnerReturn> {
|
||||||
|
const tmpDir = os.tmpdir();
|
||||||
|
const buildDir = join(tmpDir, "bwcontest-cpp");
|
||||||
|
if (fs.existsSync(buildDir)) {
|
||||||
|
fs.removeSync(buildDir);
|
||||||
|
}
|
||||||
|
fs.mkdirSync(buildDir);
|
||||||
|
|
||||||
|
console.log(`- BUILD: ${params.problemName}`);
|
||||||
|
|
||||||
|
const configureCommand = `cmake -S ${params.srcDir} -B ${buildDir}`;
|
||||||
|
try {
|
||||||
|
await execPromise(configureCommand);
|
||||||
|
} catch (e) {
|
||||||
|
const buildErrorText = e?.toString() ?? "Unknown build errors.";
|
||||||
|
console.log("Build errors: " + buildErrorText);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
runResult: { kind: "CompileFailed", resultKindReason: buildErrorText },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const compileCommand = `cmake --build ${buildDir} --target ${params.problemName}`;
|
||||||
|
try {
|
||||||
|
await execPromise(compileCommand);
|
||||||
|
} catch (e) {
|
||||||
|
const buildErrorText = e?.toString() ?? "Unknown build errors.";
|
||||||
|
console.log("Build errors: " + buildErrorText);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
runResult: { kind: "CompileFailed", resultKindReason: buildErrorText },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`- RUN: ${params.problemName}`);
|
||||||
|
|
||||||
|
let runCommand = "";
|
||||||
|
if (params.cppPlatform === "VisualStudio") {
|
||||||
|
runCommand = `${join(buildDir, "Debug", `${params.problemName}.exe`)}`;
|
||||||
|
} else {
|
||||||
|
runCommand = `${join(buildDir, params.problemName)}`;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
let outputBuffer = "";
|
||||||
|
const child = spawn(runCommand, { shell: true });
|
||||||
|
child.stdout.setEncoding("utf8");
|
||||||
|
child.stdout.on("data", (data) => {
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
});
|
||||||
|
child.stderr.setEncoding("utf8");
|
||||||
|
child.stderr.on("data", (data) => {
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
const runStartTime = performance.now();
|
||||||
|
child.stdin.write(params.input);
|
||||||
|
child.stdin.end();
|
||||||
|
|
||||||
|
let timeLimitExceeded = false;
|
||||||
|
let completedNormally = false;
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
runResult: new Promise<RunResult>((resolve) => {
|
||||||
|
child.on("close", () => {
|
||||||
|
completedNormally = !timeLimitExceeded;
|
||||||
|
|
||||||
|
const runEndTime = performance.now();
|
||||||
|
const runtimeMilliseconds = Math.floor(runEndTime - runStartTime);
|
||||||
|
|
||||||
|
if (completedNormally) {
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
resolve({
|
||||||
|
kind: "Completed",
|
||||||
|
output: outputBuffer,
|
||||||
|
exitCode: child.exitCode!,
|
||||||
|
runtimeMilliseconds,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`
|
||||||
|
);
|
||||||
|
resolve({
|
||||||
|
kind: "TimeLimitExceeded",
|
||||||
|
output: outputBuffer,
|
||||||
|
resultKindReason: `Timeout after ${timeoutSeconds} seconds`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const timeoutHandle = setTimeout(() => {
|
||||||
|
if (completedNormally) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Run timed out after ${timeoutSeconds} seconds, killing process...`
|
||||||
|
);
|
||||||
|
timeLimitExceeded = true;
|
||||||
|
|
||||||
|
child.stdin.end();
|
||||||
|
child.stdin.destroy();
|
||||||
|
child.stdout.destroy();
|
||||||
|
child.stderr.destroy();
|
||||||
|
child.kill("SIGKILL");
|
||||||
|
}, timeoutSeconds * 1000);
|
||||||
|
}),
|
||||||
|
killFunc() {
|
||||||
|
if (child.pid !== undefined) {
|
||||||
|
if (!completedNormally && !timeLimitExceeded) {
|
||||||
|
kill(child.pid);
|
||||||
|
params.outputCallback?.("\n[Manually stopped]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, runResult: { kind: "RunError" } };
|
||||||
|
}
|
||||||
|
};
|
94
shared/submission-runner/csharp.cts
Normal file
94
shared/submission-runner/csharp.cts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { spawn } from "child_process";
|
||||||
|
import kill from "tree-kill";
|
||||||
|
import type { IRunner, IRunnerReturn, RunResult } from "./types.cjs";
|
||||||
|
import { timeoutSeconds } from "./settings.cjs";
|
||||||
|
|
||||||
|
export const runCSharp: IRunner = async function (params: {
|
||||||
|
srcDir: string;
|
||||||
|
input: string;
|
||||||
|
outputCallback?: (data: string) => void;
|
||||||
|
}): Promise<IRunnerReturn> {
|
||||||
|
console.log(`- RUN: ${params.srcDir}`);
|
||||||
|
const child = spawn("dotnet run", { shell: true, cwd: params.srcDir });
|
||||||
|
|
||||||
|
try {
|
||||||
|
let outputBuffer = "";
|
||||||
|
child.stdout.setEncoding("utf8");
|
||||||
|
child.stdout.on("data", (data) => {
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
params.outputCallback?.(data.toString());
|
||||||
|
});
|
||||||
|
child.stderr.setEncoding("utf8");
|
||||||
|
child.stderr.on("data", (data) => {
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
params.outputCallback?.(data.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
const runStartTime = performance.now();
|
||||||
|
child.stdin.write(params.input);
|
||||||
|
child.stdin.end();
|
||||||
|
|
||||||
|
let timeLimitExceeded = false;
|
||||||
|
let completedNormally = false;
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
runResult: new Promise<RunResult>((resolve) => {
|
||||||
|
child.on("close", () => {
|
||||||
|
completedNormally = !timeLimitExceeded;
|
||||||
|
|
||||||
|
const runEndTime = performance.now();
|
||||||
|
const runtimeMilliseconds = Math.floor(runEndTime - runStartTime);
|
||||||
|
|
||||||
|
if (completedNormally) {
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
resolve({
|
||||||
|
kind: "Completed",
|
||||||
|
output: outputBuffer,
|
||||||
|
exitCode: child.exitCode!,
|
||||||
|
runtimeMilliseconds,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`
|
||||||
|
);
|
||||||
|
resolve({
|
||||||
|
kind: "TimeLimitExceeded",
|
||||||
|
output: outputBuffer,
|
||||||
|
resultKindReason: `Timeout after ${timeoutSeconds} seconds`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const timeoutHandle = setTimeout(() => {
|
||||||
|
if (completedNormally) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Run timed out after ${timeoutSeconds} seconds, killing process...`
|
||||||
|
);
|
||||||
|
timeLimitExceeded = true;
|
||||||
|
|
||||||
|
child.stdin.end();
|
||||||
|
child.stdin.destroy();
|
||||||
|
child.stdout.destroy();
|
||||||
|
child.stderr.destroy();
|
||||||
|
if (child.pid !== undefined) {
|
||||||
|
kill(child.pid);
|
||||||
|
}
|
||||||
|
}, timeoutSeconds * 1000);
|
||||||
|
}),
|
||||||
|
killFunc() {
|
||||||
|
if (child.pid !== undefined) {
|
||||||
|
if (!completedNormally && !timeLimitExceeded) {
|
||||||
|
kill(child.pid);
|
||||||
|
params.outputCallback?.("\n[Manually stopped]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, runResult: { kind: "RunError" } };
|
||||||
|
}
|
||||||
|
};
|
157
shared/submission-runner/dist/cpp.cjs
vendored
Normal file
157
shared/submission-runner/dist/cpp.cjs
vendored
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.runCpp = void 0;
|
||||||
|
const path_1 = require("path");
|
||||||
|
const child_process_1 = require("child_process");
|
||||||
|
const util = __importStar(require("util"));
|
||||||
|
const settings_cjs_1 = require("./settings.cjs");
|
||||||
|
const kill = __importStar(require("kill"));
|
||||||
|
const os = __importStar(require("os"));
|
||||||
|
const fs = __importStar(require("fs-extra"));
|
||||||
|
const execPromise = util.promisify(child_process_1.exec);
|
||||||
|
const runCpp = function (params) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
var _a, _b;
|
||||||
|
const tmpDir = os.tmpdir();
|
||||||
|
const buildDir = (0, path_1.join)(tmpDir, "bwcontest-cpp");
|
||||||
|
if (fs.existsSync(buildDir)) {
|
||||||
|
fs.removeSync(buildDir);
|
||||||
|
}
|
||||||
|
fs.mkdirSync(buildDir);
|
||||||
|
console.log(`- BUILD: ${params.problemName}`);
|
||||||
|
const configureCommand = `cmake -S ${params.srcDir} -B ${buildDir}`;
|
||||||
|
try {
|
||||||
|
yield execPromise(configureCommand);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
const buildErrorText = (_a = e === null || e === void 0 ? void 0 : e.toString()) !== null && _a !== void 0 ? _a : "Unknown build errors.";
|
||||||
|
console.log("Build errors: " + buildErrorText);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
runResult: { kind: "CompileFailed", resultKindReason: buildErrorText },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const compileCommand = `cmake --build ${buildDir} --target ${params.problemName}`;
|
||||||
|
try {
|
||||||
|
yield execPromise(compileCommand);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
const buildErrorText = (_b = e === null || e === void 0 ? void 0 : e.toString()) !== null && _b !== void 0 ? _b : "Unknown build errors.";
|
||||||
|
console.log("Build errors: " + buildErrorText);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
runResult: { kind: "CompileFailed", resultKindReason: buildErrorText },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(`- RUN: ${params.problemName}`);
|
||||||
|
let runCommand = "";
|
||||||
|
if (params.cppPlatform === "VisualStudio") {
|
||||||
|
runCommand = `${(0, path_1.join)(buildDir, "Debug", `${params.problemName}.exe`)}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
runCommand = `${(0, path_1.join)(buildDir, params.problemName)}`;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
let outputBuffer = "";
|
||||||
|
const child = (0, child_process_1.spawn)(runCommand, { shell: true });
|
||||||
|
child.stdout.setEncoding("utf8");
|
||||||
|
child.stdout.on("data", (data) => {
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
});
|
||||||
|
child.stderr.setEncoding("utf8");
|
||||||
|
child.stderr.on("data", (data) => {
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
});
|
||||||
|
const runStartTime = performance.now();
|
||||||
|
child.stdin.write(params.input);
|
||||||
|
child.stdin.end();
|
||||||
|
let timeLimitExceeded = false;
|
||||||
|
let completedNormally = false;
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
runResult: new Promise((resolve) => {
|
||||||
|
child.on("close", () => {
|
||||||
|
completedNormally = !timeLimitExceeded;
|
||||||
|
const runEndTime = performance.now();
|
||||||
|
const runtimeMilliseconds = Math.floor(runEndTime - runStartTime);
|
||||||
|
if (completedNormally) {
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
resolve({
|
||||||
|
kind: "Completed",
|
||||||
|
output: outputBuffer,
|
||||||
|
exitCode: child.exitCode,
|
||||||
|
runtimeMilliseconds,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`);
|
||||||
|
resolve({
|
||||||
|
kind: "TimeLimitExceeded",
|
||||||
|
output: outputBuffer,
|
||||||
|
resultKindReason: `Timeout after ${settings_cjs_1.timeoutSeconds} seconds`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const timeoutHandle = setTimeout(() => {
|
||||||
|
if (completedNormally) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`Run timed out after ${settings_cjs_1.timeoutSeconds} seconds, killing process...`);
|
||||||
|
timeLimitExceeded = true;
|
||||||
|
child.stdin.end();
|
||||||
|
child.stdin.destroy();
|
||||||
|
child.stdout.destroy();
|
||||||
|
child.stderr.destroy();
|
||||||
|
child.kill("SIGKILL");
|
||||||
|
}, settings_cjs_1.timeoutSeconds * 1000);
|
||||||
|
}),
|
||||||
|
killFunc() {
|
||||||
|
var _a;
|
||||||
|
if (child.pid !== undefined) {
|
||||||
|
if (!completedNormally && !timeLimitExceeded) {
|
||||||
|
kill(child.pid);
|
||||||
|
(_a = params.outputCallback) === null || _a === void 0 ? void 0 : _a.call(params, "\n[Manually stopped]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
return { success: false, runResult: { kind: "RunError" } };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.runCpp = runCpp;
|
||||||
|
//# sourceMappingURL=cpp.cjs.map
|
1
shared/submission-runner/dist/cpp.cjs.map
vendored
Normal file
1
shared/submission-runner/dist/cpp.cjs.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"cpp.cjs","sourceRoot":"","sources":["../cpp.cts"],"names":[],"mappings":"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"}
|
12
shared/submission-runner/dist/cpp.d.cts
vendored
Normal file
12
shared/submission-runner/dist/cpp.d.cts
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import type { IRunner, IRunnerParams } from "./types.cjs";
|
||||||
|
export type CppPlatform = "VisualStudio" | "GCC";
|
||||||
|
interface IRunnerParamsCpp extends IRunnerParams {
|
||||||
|
srcDir: string;
|
||||||
|
problemName: string;
|
||||||
|
input: string;
|
||||||
|
cppPlatform: CppPlatform;
|
||||||
|
outputCallback?: (data: string) => void;
|
||||||
|
}
|
||||||
|
export declare const runCpp: IRunner<IRunnerParamsCpp>;
|
||||||
|
export {};
|
||||||
|
//# sourceMappingURL=cpp.d.cts.map
|
1
shared/submission-runner/dist/cpp.d.cts.map
vendored
Normal file
1
shared/submission-runner/dist/cpp.d.cts.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"cpp.d.cts","sourceRoot":"","sources":["../cpp.cts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,OAAO,EACP,aAAa,EAGd,MAAM,aAAa,CAAC;AAQrB,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;AAEjD,UAAU,gBAAiB,SAAQ,aAAa;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,eAAO,MAAM,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAyH5C,CAAC"}
|
119
shared/submission-runner/dist/csharp.cjs
vendored
Normal file
119
shared/submission-runner/dist/csharp.cjs
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.runCSharp = void 0;
|
||||||
|
const child_process_1 = require("child_process");
|
||||||
|
const kill = __importStar(require("tree-kill"));
|
||||||
|
const settings_cjs_1 = require("./settings.cjs");
|
||||||
|
const runCSharp = function (params) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
console.log(`- RUN: ${params.srcDir}`);
|
||||||
|
const child = (0, child_process_1.spawn)("dotnet run", { shell: true, cwd: params.srcDir });
|
||||||
|
try {
|
||||||
|
let outputBuffer = "";
|
||||||
|
child.stdout.setEncoding("utf8");
|
||||||
|
child.stdout.on("data", (data) => {
|
||||||
|
var _a;
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
(_a = params.outputCallback) === null || _a === void 0 ? void 0 : _a.call(params, data.toString());
|
||||||
|
});
|
||||||
|
child.stderr.setEncoding("utf8");
|
||||||
|
child.stderr.on("data", (data) => {
|
||||||
|
var _a;
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
(_a = params.outputCallback) === null || _a === void 0 ? void 0 : _a.call(params, data.toString());
|
||||||
|
});
|
||||||
|
const runStartTime = performance.now();
|
||||||
|
child.stdin.write(params.input);
|
||||||
|
child.stdin.end();
|
||||||
|
let timeLimitExceeded = false;
|
||||||
|
let completedNormally = false;
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
runResult: new Promise((resolve) => {
|
||||||
|
child.on("close", () => {
|
||||||
|
completedNormally = !timeLimitExceeded;
|
||||||
|
const runEndTime = performance.now();
|
||||||
|
const runtimeMilliseconds = Math.floor(runEndTime - runStartTime);
|
||||||
|
if (completedNormally) {
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
resolve({
|
||||||
|
kind: "Completed",
|
||||||
|
output: outputBuffer,
|
||||||
|
exitCode: child.exitCode,
|
||||||
|
runtimeMilliseconds,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`);
|
||||||
|
resolve({
|
||||||
|
kind: "TimeLimitExceeded",
|
||||||
|
output: outputBuffer,
|
||||||
|
resultKindReason: `Timeout after ${settings_cjs_1.timeoutSeconds} seconds`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const timeoutHandle = setTimeout(() => {
|
||||||
|
if (completedNormally) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`Run timed out after ${settings_cjs_1.timeoutSeconds} seconds, killing process...`);
|
||||||
|
timeLimitExceeded = true;
|
||||||
|
child.stdin.end();
|
||||||
|
child.stdin.destroy();
|
||||||
|
child.stdout.destroy();
|
||||||
|
child.stderr.destroy();
|
||||||
|
if (child.pid !== undefined) {
|
||||||
|
kill(child.pid);
|
||||||
|
}
|
||||||
|
}, settings_cjs_1.timeoutSeconds * 1000);
|
||||||
|
}),
|
||||||
|
killFunc() {
|
||||||
|
var _a;
|
||||||
|
if (child.pid !== undefined) {
|
||||||
|
if (!completedNormally && !timeLimitExceeded) {
|
||||||
|
kill(child.pid);
|
||||||
|
(_a = params.outputCallback) === null || _a === void 0 ? void 0 : _a.call(params, "\n[Manually stopped]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
return { success: false, runResult: { kind: "RunError" } };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.runCSharp = runCSharp;
|
||||||
|
//# sourceMappingURL=csharp.cjs.map
|
1
shared/submission-runner/dist/csharp.cjs.map
vendored
Normal file
1
shared/submission-runner/dist/csharp.cjs.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"csharp.cjs","sourceRoot":"","sources":["../csharp.cts"],"names":[],"mappings":"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"}
|
3
shared/submission-runner/dist/csharp.d.cts
vendored
Normal file
3
shared/submission-runner/dist/csharp.d.cts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import type { IRunner } from "./types.cjs";
|
||||||
|
export declare const runCSharp: IRunner;
|
||||||
|
//# sourceMappingURL=csharp.d.cts.map
|
1
shared/submission-runner/dist/csharp.d.cts.map
vendored
Normal file
1
shared/submission-runner/dist/csharp.d.cts.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"csharp.d.cts","sourceRoot":"","sources":["../csharp.cts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAA4B,MAAM,aAAa,CAAC;AAGrE,eAAO,MAAM,SAAS,EAAE,OAwFvB,CAAC"}
|
135
shared/submission-runner/dist/java.cjs
vendored
Normal file
135
shared/submission-runner/dist/java.cjs
vendored
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.runJava = void 0;
|
||||||
|
const path_1 = require("path");
|
||||||
|
const child_process_1 = require("child_process");
|
||||||
|
const util = __importStar(require("util"));
|
||||||
|
const settings_cjs_1 = require("./settings.cjs");
|
||||||
|
const kill = require("tree-kill");
|
||||||
|
const execPromise = util.promisify(child_process_1.exec);
|
||||||
|
const runJava = function (params) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
var _a;
|
||||||
|
console.log(`- BUILD: ${params.mainFile}`);
|
||||||
|
const compileCommand = `javac -cp ${(0, path_1.join)(params.srcDir, 'src')} ${params.mainFile} -d ${(0, path_1.join)(params.srcDir, 'build')}`;
|
||||||
|
try {
|
||||||
|
yield execPromise(compileCommand);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
const buildErrorText = (_a = e === null || e === void 0 ? void 0 : e.toString()) !== null && _a !== void 0 ? _a : 'Unknown build errors.';
|
||||||
|
console.log('Build errors: ' + buildErrorText);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
runResult: { kind: 'CompileFailed', resultKindReason: buildErrorText }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(`- RUN: ${params.mainClass}`);
|
||||||
|
const runCommand = `java -cp "${(0, path_1.join)(params.srcDir, 'build')}" ${params.mainClass}`;
|
||||||
|
try {
|
||||||
|
let outputBuffer = '';
|
||||||
|
const child = (0, child_process_1.spawn)(runCommand, { shell: true });
|
||||||
|
child.stdout.setEncoding('utf8');
|
||||||
|
child.stdout.on('data', (data) => {
|
||||||
|
var _a;
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
(_a = params.outputCallback) === null || _a === void 0 ? void 0 : _a.call(params, data.toString());
|
||||||
|
});
|
||||||
|
child.stderr.setEncoding('utf8');
|
||||||
|
child.stderr.on('data', (data) => {
|
||||||
|
var _a;
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
(_a = params.outputCallback) === null || _a === void 0 ? void 0 : _a.call(params, data.toString());
|
||||||
|
});
|
||||||
|
const runStartTime = performance.now();
|
||||||
|
child.stdin.write(params.input);
|
||||||
|
child.stdin.end();
|
||||||
|
let timeLimitExceeded = false;
|
||||||
|
let completedNormally = false;
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
runResult: new Promise((resolve) => {
|
||||||
|
child.on('close', () => {
|
||||||
|
completedNormally = !timeLimitExceeded;
|
||||||
|
const runEndTime = performance.now();
|
||||||
|
const runtimeMilliseconds = Math.floor(runEndTime - runStartTime);
|
||||||
|
if (completedNormally) {
|
||||||
|
clearTimeout(timeoutHandle);
|
||||||
|
resolve({
|
||||||
|
kind: 'Completed',
|
||||||
|
output: outputBuffer,
|
||||||
|
exitCode: child.exitCode,
|
||||||
|
runtimeMilliseconds
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`);
|
||||||
|
resolve({
|
||||||
|
kind: 'TimeLimitExceeded',
|
||||||
|
output: outputBuffer,
|
||||||
|
resultKindReason: `Timeout after ${settings_cjs_1.timeoutSeconds} seconds`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const timeoutHandle = setTimeout(() => {
|
||||||
|
if (completedNormally) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`Run timed out after ${settings_cjs_1.timeoutSeconds} seconds, killing process...`);
|
||||||
|
timeLimitExceeded = true;
|
||||||
|
child.stdin.end();
|
||||||
|
child.stdin.destroy();
|
||||||
|
child.stdout.destroy();
|
||||||
|
child.stderr.destroy();
|
||||||
|
child.kill('SIGKILL');
|
||||||
|
}, settings_cjs_1.timeoutSeconds * 1000);
|
||||||
|
}),
|
||||||
|
killFunc() {
|
||||||
|
var _a;
|
||||||
|
if (child.pid !== undefined) {
|
||||||
|
if (!completedNormally && !timeLimitExceeded) {
|
||||||
|
kill(child.pid);
|
||||||
|
(_a = params.outputCallback) === null || _a === void 0 ? void 0 : _a.call(params, '\n[Manually stopped]');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
return { success: false, runResult: { kind: 'RunError' } };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.runJava = runJava;
|
||||||
|
//# sourceMappingURL=java.cjs.map
|
1
shared/submission-runner/dist/java.cjs.map
vendored
Normal file
1
shared/submission-runner/dist/java.cjs.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"java.cjs","sourceRoot":"","sources":["../java.cts"],"names":[],"mappings":"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"}
|
11
shared/submission-runner/dist/java.d.cts
vendored
Normal file
11
shared/submission-runner/dist/java.d.cts
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import type { IRunner, IRunnerParams } from './types.cjs';
|
||||||
|
interface IRunnerParamsJava extends IRunnerParams {
|
||||||
|
srcDir: string;
|
||||||
|
mainFile: string;
|
||||||
|
mainClass: string;
|
||||||
|
input: string;
|
||||||
|
outputCallback?: (data: string) => void;
|
||||||
|
}
|
||||||
|
export declare const runJava: IRunner<IRunnerParamsJava>;
|
||||||
|
export {};
|
||||||
|
//# sourceMappingURL=java.d.cts.map
|
1
shared/submission-runner/dist/java.d.cts.map
vendored
Normal file
1
shared/submission-runner/dist/java.d.cts.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"java.d.cts","sourceRoot":"","sources":["../java.cts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAA4B,MAAM,aAAa,CAAC;AAOpF,UAAU,iBAAkB,SAAQ,aAAa;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,iBAAiB,CA+F9C,CAAC"}
|
5
shared/submission-runner/dist/settings.cjs
vendored
Normal file
5
shared/submission-runner/dist/settings.cjs
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.timeoutSeconds = void 0;
|
||||||
|
exports.timeoutSeconds = 30;
|
||||||
|
//# sourceMappingURL=settings.cjs.map
|
1
shared/submission-runner/dist/settings.cjs.map
vendored
Normal file
1
shared/submission-runner/dist/settings.cjs.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"settings.cjs","sourceRoot":"","sources":["../settings.cts"],"names":[],"mappings":";;;AAAa,QAAA,cAAc,GAAG,EAAE,CAAC"}
|
2
shared/submission-runner/dist/settings.d.cts
vendored
Normal file
2
shared/submission-runner/dist/settings.d.cts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export declare const timeoutSeconds = 30;
|
||||||
|
//# sourceMappingURL=settings.d.cts.map
|
1
shared/submission-runner/dist/settings.d.cts.map
vendored
Normal file
1
shared/submission-runner/dist/settings.d.cts.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"settings.d.cts","sourceRoot":"","sources":["../settings.cts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,KAAK,CAAC"}
|
1
shared/submission-runner/dist/tsconfig.tsbuildinfo
vendored
Normal file
1
shared/submission-runner/dist/tsconfig.tsbuildinfo
vendored
Normal file
File diff suppressed because one or more lines are too long
21
shared/submission-runner/dist/types.cjs
vendored
Normal file
21
shared/submission-runner/dist/types.cjs
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.RunResultZod = void 0;
|
||||||
|
const zod_1 = require("zod");
|
||||||
|
const RunResultKind = zod_1.z.enum([
|
||||||
|
'CompileFailed',
|
||||||
|
'TimeLimitExceeded',
|
||||||
|
'Completed',
|
||||||
|
'SandboxError',
|
||||||
|
'RunError'
|
||||||
|
]);
|
||||||
|
exports.RunResultZod = zod_1.z
|
||||||
|
.object({
|
||||||
|
kind: RunResultKind,
|
||||||
|
output: zod_1.z.string().optional(),
|
||||||
|
exitCode: zod_1.z.number().optional(),
|
||||||
|
runtimeMilliseconds: zod_1.z.number().optional(),
|
||||||
|
resultKindReason: zod_1.z.string().optional()
|
||||||
|
})
|
||||||
|
.strict();
|
||||||
|
//# sourceMappingURL=types.cjs.map
|
1
shared/submission-runner/dist/types.cjs.map
vendored
Normal file
1
shared/submission-runner/dist/types.cjs.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"types.cjs","sourceRoot":"","sources":["../types.cts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAExB,MAAM,aAAa,GAAG,OAAC,CAAC,IAAI,CAAC;IAC5B,eAAe;IACf,mBAAmB;IACnB,WAAW;IACX,cAAc;IACd,UAAU;CACV,CAAC,CAAC;AAIU,QAAA,YAAY,GAAG,OAAC;KAC3B,MAAM,CAAC;IACP,IAAI,EAAE,aAAa;IACnB,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,mBAAmB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACvC,CAAC;KACD,MAAM,EAAE,CAAC"}
|
39
shared/submission-runner/dist/types.d.cts
vendored
Normal file
39
shared/submission-runner/dist/types.d.cts
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
declare const RunResultKind: z.ZodEnum<["CompileFailed", "TimeLimitExceeded", "Completed", "SandboxError", "RunError"]>;
|
||||||
|
export type RunResultKind = z.infer<typeof RunResultKind>;
|
||||||
|
export declare const RunResultZod: z.ZodObject<{
|
||||||
|
kind: z.ZodEnum<["CompileFailed", "TimeLimitExceeded", "Completed", "SandboxError", "RunError"]>;
|
||||||
|
output: z.ZodOptional<z.ZodString>;
|
||||||
|
exitCode: z.ZodOptional<z.ZodNumber>;
|
||||||
|
runtimeMilliseconds: z.ZodOptional<z.ZodNumber>;
|
||||||
|
resultKindReason: z.ZodOptional<z.ZodString>;
|
||||||
|
}, "strict", z.ZodTypeAny, {
|
||||||
|
kind: "CompileFailed" | "TimeLimitExceeded" | "Completed" | "SandboxError" | "RunError";
|
||||||
|
output?: string | undefined;
|
||||||
|
exitCode?: number | undefined;
|
||||||
|
runtimeMilliseconds?: number | undefined;
|
||||||
|
resultKindReason?: string | undefined;
|
||||||
|
}, {
|
||||||
|
kind: "CompileFailed" | "TimeLimitExceeded" | "Completed" | "SandboxError" | "RunError";
|
||||||
|
output?: string | undefined;
|
||||||
|
exitCode?: number | undefined;
|
||||||
|
runtimeMilliseconds?: number | undefined;
|
||||||
|
resultKindReason?: string | undefined;
|
||||||
|
}>;
|
||||||
|
export type RunResult = z.infer<typeof RunResultZod>;
|
||||||
|
export interface IRunnerParams {
|
||||||
|
srcDir: string;
|
||||||
|
input: string;
|
||||||
|
outputCallback?: (data: string) => void;
|
||||||
|
}
|
||||||
|
export type IRunnerReturn = {
|
||||||
|
success: true;
|
||||||
|
killFunc: () => void;
|
||||||
|
runResult: Promise<RunResult>;
|
||||||
|
} | {
|
||||||
|
success: false;
|
||||||
|
runResult: RunResult;
|
||||||
|
};
|
||||||
|
export type IRunner<T extends IRunnerParams = IRunnerParams> = (params: T) => Promise<IRunnerReturn>;
|
||||||
|
export {};
|
||||||
|
//# sourceMappingURL=types.d.cts.map
|
1
shared/submission-runner/dist/types.d.cts.map
vendored
Normal file
1
shared/submission-runner/dist/types.d.cts.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../types.cts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,aAAa,4FAMjB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;EAQf,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAErD,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,MAAM,aAAa,GACxB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;CAAE,GACtE;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,CAAC;AAE1C,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAC1D,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC"}
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"name": "submission-runner",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc"
|
"build": "tsc"
|
||||||
},
|
},
|
@ -6,9 +6,9 @@
|
|||||||
"declaration": true,
|
"declaration": true,
|
||||||
"declarationMap": true,
|
"declarationMap": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "./build",
|
"outDir": "./dist",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
},
|
},
|
||||||
"include": ["/**/*.cts"]
|
"include": ["*.cts"]
|
||||||
}
|
}
|
2
shared/submissionRunner/.gitignore
vendored
2
shared/submissionRunner/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
/build
|
|
@ -1,139 +0,0 @@
|
|||||||
import { join } from 'path';
|
|
||||||
import { exec, spawn } from 'child_process';
|
|
||||||
import util from 'util';
|
|
||||||
import type { IRunner, IRunnerParams, IRunnerReturn, RunResult } from './types.cjs';
|
|
||||||
import { timeoutSeconds } from './settings.cjs';
|
|
||||||
import kill from 'tree-kill';
|
|
||||||
import os from 'os';
|
|
||||||
import fs from 'fs-extra';
|
|
||||||
|
|
||||||
const execPromise = util.promisify(exec);
|
|
||||||
|
|
||||||
export type CppPlatform = 'VisualStudio' | 'GCC';
|
|
||||||
|
|
||||||
interface IRunnerParamsCpp extends IRunnerParams {
|
|
||||||
srcDir: string;
|
|
||||||
problemName: string;
|
|
||||||
input: string;
|
|
||||||
cppPlatform: CppPlatform;
|
|
||||||
outputCallback?: (data: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const runCpp: IRunner<IRunnerParamsCpp> = async function (
|
|
||||||
params: IRunnerParamsCpp
|
|
||||||
): Promise<IRunnerReturn> {
|
|
||||||
const tmpDir = os.tmpdir();
|
|
||||||
const buildDir = join(tmpDir, 'bwcontest-cpp');
|
|
||||||
if (fs.existsSync(buildDir)) {
|
|
||||||
fs.removeSync(buildDir);
|
|
||||||
}
|
|
||||||
fs.mkdirSync(buildDir);
|
|
||||||
|
|
||||||
console.log(`- BUILD: ${params.problemName}`);
|
|
||||||
|
|
||||||
const configureCommand = `cmake -S ${params.srcDir} -B ${buildDir}`;
|
|
||||||
try {
|
|
||||||
await execPromise(configureCommand);
|
|
||||||
} catch (e) {
|
|
||||||
const buildErrorText = e?.toString() ?? 'Unknown build errors.';
|
|
||||||
console.log('Build errors: ' + buildErrorText);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
runResult: { kind: 'CompileFailed', resultKindReason: buildErrorText }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const compileCommand = `cmake --build ${buildDir} --target ${params.problemName}`;
|
|
||||||
try {
|
|
||||||
await execPromise(compileCommand);
|
|
||||||
} catch (e) {
|
|
||||||
const buildErrorText = e?.toString() ?? 'Unknown build errors.';
|
|
||||||
console.log('Build errors: ' + buildErrorText);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
runResult: { kind: 'CompileFailed', resultKindReason: buildErrorText }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`- RUN: ${params.problemName}`);
|
|
||||||
|
|
||||||
let runCommand = '';
|
|
||||||
if (params.cppPlatform === 'VisualStudio') {
|
|
||||||
runCommand = `${join(buildDir, 'Debug', `${params.problemName}.exe`)}`;
|
|
||||||
} else {
|
|
||||||
runCommand = `${join(buildDir, params.problemName)}`;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
let outputBuffer = '';
|
|
||||||
const child = spawn(runCommand, { shell: true });
|
|
||||||
child.stdout.setEncoding('utf8');
|
|
||||||
child.stdout.on('data', (data) => {
|
|
||||||
outputBuffer += data.toString();
|
|
||||||
});
|
|
||||||
child.stderr.setEncoding('utf8');
|
|
||||||
child.stderr.on('data', (data) => {
|
|
||||||
outputBuffer += data.toString();
|
|
||||||
});
|
|
||||||
|
|
||||||
const runStartTime = performance.now();
|
|
||||||
child.stdin.write(params.input);
|
|
||||||
child.stdin.end();
|
|
||||||
|
|
||||||
let timeLimitExceeded = false;
|
|
||||||
let completedNormally = false;
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
runResult: new Promise<RunResult>((resolve) => {
|
|
||||||
child.on('close', () => {
|
|
||||||
completedNormally = !timeLimitExceeded;
|
|
||||||
|
|
||||||
const runEndTime = performance.now();
|
|
||||||
const runtimeMilliseconds = Math.floor(runEndTime - runStartTime);
|
|
||||||
|
|
||||||
if (completedNormally) {
|
|
||||||
clearTimeout(timeoutHandle);
|
|
||||||
resolve({
|
|
||||||
kind: 'Completed',
|
|
||||||
output: outputBuffer,
|
|
||||||
exitCode: child.exitCode!,
|
|
||||||
runtimeMilliseconds
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log(`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`);
|
|
||||||
resolve({
|
|
||||||
kind: 'TimeLimitExceeded',
|
|
||||||
output: outputBuffer,
|
|
||||||
resultKindReason: `Timeout after ${timeoutSeconds} seconds`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const timeoutHandle = setTimeout(() => {
|
|
||||||
if (completedNormally) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Run timed out after ${timeoutSeconds} seconds, killing process...`);
|
|
||||||
timeLimitExceeded = true;
|
|
||||||
|
|
||||||
child.stdin.end();
|
|
||||||
child.stdin.destroy();
|
|
||||||
child.stdout.destroy();
|
|
||||||
child.stderr.destroy();
|
|
||||||
child.kill('SIGKILL');
|
|
||||||
}, timeoutSeconds * 1000);
|
|
||||||
}),
|
|
||||||
killFunc() {
|
|
||||||
if (child.pid !== undefined) {
|
|
||||||
if (!completedNormally && !timeLimitExceeded) {
|
|
||||||
kill(child.pid);
|
|
||||||
params.outputCallback?.('\n[Manually stopped]');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return { success: false, runResult: { kind: 'RunError' } };
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,90 +0,0 @@
|
|||||||
import { spawn } from 'child_process';
|
|
||||||
import kill from 'tree-kill';
|
|
||||||
import type { IRunner, IRunnerReturn, RunResult } from './types.cjs';
|
|
||||||
import { timeoutSeconds } from './settings.cjs';
|
|
||||||
|
|
||||||
export const runCSharp: IRunner = async function (params: {
|
|
||||||
srcDir: string;
|
|
||||||
input: string;
|
|
||||||
outputCallback?: (data: string) => void;
|
|
||||||
}): Promise<IRunnerReturn> {
|
|
||||||
console.log(`- RUN: ${params.srcDir}`);
|
|
||||||
const child = spawn('dotnet run', { shell: true, cwd: params.srcDir });
|
|
||||||
|
|
||||||
try {
|
|
||||||
let outputBuffer = '';
|
|
||||||
child.stdout.setEncoding('utf8');
|
|
||||||
child.stdout.on('data', (data) => {
|
|
||||||
outputBuffer += data.toString();
|
|
||||||
params.outputCallback?.(data.toString());
|
|
||||||
});
|
|
||||||
child.stderr.setEncoding('utf8');
|
|
||||||
child.stderr.on('data', (data) => {
|
|
||||||
outputBuffer += data.toString();
|
|
||||||
params.outputCallback?.(data.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
const runStartTime = performance.now();
|
|
||||||
child.stdin.write(params.input);
|
|
||||||
child.stdin.end();
|
|
||||||
|
|
||||||
let timeLimitExceeded = false;
|
|
||||||
let completedNormally = false;
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
runResult: new Promise<RunResult>((resolve) => {
|
|
||||||
child.on('close', () => {
|
|
||||||
completedNormally = !timeLimitExceeded;
|
|
||||||
|
|
||||||
const runEndTime = performance.now();
|
|
||||||
const runtimeMilliseconds = Math.floor(runEndTime - runStartTime);
|
|
||||||
|
|
||||||
if (completedNormally) {
|
|
||||||
clearTimeout(timeoutHandle);
|
|
||||||
resolve({
|
|
||||||
kind: 'Completed',
|
|
||||||
output: outputBuffer,
|
|
||||||
exitCode: child.exitCode!,
|
|
||||||
runtimeMilliseconds
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log(`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`);
|
|
||||||
resolve({
|
|
||||||
kind: 'TimeLimitExceeded',
|
|
||||||
output: outputBuffer,
|
|
||||||
resultKindReason: `Timeout after ${timeoutSeconds} seconds`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const timeoutHandle = setTimeout(() => {
|
|
||||||
if (completedNormally) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Run timed out after ${timeoutSeconds} seconds, killing process...`);
|
|
||||||
timeLimitExceeded = true;
|
|
||||||
|
|
||||||
child.stdin.end();
|
|
||||||
child.stdin.destroy();
|
|
||||||
child.stdout.destroy();
|
|
||||||
child.stderr.destroy();
|
|
||||||
if (child.pid !== undefined) {
|
|
||||||
kill(child.pid);
|
|
||||||
}
|
|
||||||
}, timeoutSeconds * 1000);
|
|
||||||
}),
|
|
||||||
killFunc() {
|
|
||||||
if (child.pid !== undefined) {
|
|
||||||
if (!completedNormally && !timeLimitExceeded) {
|
|
||||||
kill(child.pid);
|
|
||||||
params.outputCallback?.('\n[Manually stopped]');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return { success: false, runResult: { kind: 'RunError' } };
|
|
||||||
}
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user