mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-21 01:46:28 +08:00
judge: handle optional stdin and redirection
This commit is contained in:
1 parent
5dfb81c6c3
commit
9d0aeebe12
5 files changed
+59
-72
No files matched your search
@@ -6,7 +6,7 @@ import { STATUS } from '@hydrooj/utils/lib/status';
|
||||
import { getConfig } from './config';
|
||||
import { FormatError, SystemError } from './error';
|
||||
import { Logger } from './log';
|
||||
import { SandboxClient } from './sandbox/client';
|
||||
import client from './sandbox/client';
|
||||
import {
|
||||
Cmd, CopyIn, CopyInFile, SandboxResult, SandboxStatus,
|
||||
} from './sandbox/interface';
|
||||
@@ -41,6 +41,8 @@ interface Parameter {
|
||||
copyOutCached?: string[];
|
||||
cacheStdoutAndStderr?: boolean;
|
||||
env?: Record<string, string>;
|
||||
/** redirect stdin & stdout */
|
||||
filename?: string;
|
||||
}
|
||||
|
||||
interface SandboxAdaptedResult {
|
||||
@@ -69,29 +71,24 @@ function parseArgs(execute: string): string[] {
|
||||
return args;
|
||||
}
|
||||
|
||||
function proc({
|
||||
execute = '',
|
||||
time = 16000,
|
||||
memory = parseMemoryMB(getConfig('memoryMax')),
|
||||
processLimit = getConfig('processLimit'),
|
||||
stdin = { content: '' }, copyIn = {}, copyOut = [], copyOutCached = [],
|
||||
cacheStdoutAndStderr = false,
|
||||
env = {},
|
||||
}: Parameter = {}): Cmd {
|
||||
if (!supportOptional) {
|
||||
copyOut = copyOut.map((i) => (i.endsWith('?') ? i.substring(0, i.length - 1) : i));
|
||||
}
|
||||
function proc(params: Parameter): Cmd {
|
||||
const copyOut = supportOptional
|
||||
? params.copyOut
|
||||
: params.copyOut.map((i) => (i.endsWith('?') ? i.substring(0, i.length - 1) : i));
|
||||
const size = parseMemoryMB(getConfig('stdio_size'));
|
||||
const rate = getConfig('rate');
|
||||
const copyOutCachedCopy = [...copyOutCached];
|
||||
if (cacheStdoutAndStderr) {
|
||||
copyOutCachedCopy.push('stdout', 'stderr');
|
||||
}
|
||||
const copyOutCached = [...(params.copyOutCached || [])];
|
||||
if (params.cacheStdoutAndStderr) copyOutCached.push(params.filename ? `${params.filename}.out` : 'stdout', 'stderr');
|
||||
const copyIn = { ...(params.copyIn || {}) };
|
||||
const stdin = params.stdin || { content: '' };
|
||||
if (params.filename) copyIn[`${params.filename}.in`] = stdin;
|
||||
const time = params.time || 16000;
|
||||
const memory = params.memory || parseMemoryMB(getConfig('memoryMax'));
|
||||
return {
|
||||
args: parseArgs(execute),
|
||||
env: [...getConfig('env').split('\n'), ...Object.keys(env).map((i) => `${i}=${env[i].replace(/=/g, '\\=')}`)],
|
||||
args: parseArgs(params.execute || ''),
|
||||
env: [...getConfig('env').split('\n'), ...Object.entries(params.env || {}).map(([k, v]) => `${k}=${v.replace(/=/g, '\\=')}`)],
|
||||
files: [
|
||||
stdin,
|
||||
params.filename ? { content: '' } : stdin,
|
||||
{ name: 'stdout', max: Math.floor(1024 * 1024 * size) },
|
||||
{ name: 'stderr', max: Math.floor(1024 * 1024 * size) },
|
||||
],
|
||||
@@ -100,10 +97,10 @@ function proc({
|
||||
memoryLimit: Math.floor(memory * 1024 * 1024),
|
||||
strictMemoryLimit: getConfig('strict_memory'),
|
||||
// stackLimit: memory * 1024 * 1024,
|
||||
procLimit: processLimit,
|
||||
procLimit: params.processLimit || getConfig('processLimit'),
|
||||
copyIn,
|
||||
copyOut,
|
||||
copyOutCached: copyOutCachedCopy,
|
||||
copyOutCached,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -120,10 +117,12 @@ async function adaptResult(result: SandboxResult, params: Parameter): Promise<Sa
|
||||
if (ret.time >= (params.time || 16000)) {
|
||||
ret.status = STATUS.STATUS_TIME_LIMIT_EXCEEDED;
|
||||
}
|
||||
const outname = params.filename ? `${params.filename}.out` : 'stdout';
|
||||
ret.files = result.files || {};
|
||||
ret.fileIds = result.fileIds || {};
|
||||
if (params.stdout) await fs.writeFile(params.stdout, ret.files.stdout || '');
|
||||
else ret.stdout = ret.files.stdout || '';
|
||||
if (ret.fileIds[outname]) ret.fileIds.stdout = ret.fileIds[outname];
|
||||
if (params.stdout) await fs.writeFile(params.stdout, ret.files[outname] || '');
|
||||
else ret.stdout = ret.files[outname] || '';
|
||||
if (params.stderr) await fs.writeFile(params.stderr, ret.files.stderr || result.error || '');
|
||||
else ret.stderr = ret.files.stderr || result.error || '';
|
||||
if (result.error) ret.error = result.error;
|
||||
@@ -159,7 +158,7 @@ export async function runPiped(execute0: Parameter, execute1: Parameter): Promis
|
||||
body.cmd[1].files[1] = null;
|
||||
const id = callId++;
|
||||
if (argv.options.showSandbox) logger.debug('%d %s', id, JSON.stringify(body));
|
||||
res = await new SandboxClient(getConfig('sandbox_host')).run(body);
|
||||
res = await client.run(body);
|
||||
if (argv.options.showSandbox) logger.debug('%d %s', id, JSON.stringify(res));
|
||||
} catch (e) {
|
||||
if (e instanceof FormatError || e instanceof SystemError) throw e;
|
||||
@@ -170,13 +169,12 @@ export async function runPiped(execute0: Parameter, execute1: Parameter): Promis
|
||||
}
|
||||
|
||||
export async function del(fileId: string) {
|
||||
await new SandboxClient(getConfig('sandbox_host')).deleteFile(fileId);
|
||||
await client.deleteFile(fileId);
|
||||
}
|
||||
|
||||
export async function run(execute: string, params?: Parameter): Promise<SandboxAdaptedResult> {
|
||||
let result: SandboxResult;
|
||||
try {
|
||||
const client = new SandboxClient(getConfig('sandbox_host'));
|
||||
if (!supportOptional) {
|
||||
const res = await client.version();
|
||||
supportOptional = res.copyOutOptional;
|
||||
|
||||
Reference in new issue
Block a user