Search in sources :

Example 1 with NotExecutableException

use of cn.edu.zjnu.acm.judge.core.NotExecutableException in project judge by zjnu-acm.

the class WindowsExecutor method createProcess.

private PROCESS_INFORMATION createProcess(String lpCommandLine, long hIn, long hOut, long hErr, boolean redirectErrorStream, Path lpCurrentDirectory) {
    STARTUPINFO startupInfo = new STARTUPINFO();
    startupInfo.setCb(startupInfo.size());
    startupInfo.setDesktop(DESKTOP);
    PROCESS_INFORMATION lpProcessInformation = new PROCESS_INFORMATION();
    // without cursor feed back
    startupInfo.setFlags(STARTF_USESTDHANDLES | STARTF_FORCEOFFFEEDBACK);
    startupInfo.setStdInput(hIn);
    startupInfo.setStdOutput(hOut);
    startupInfo.setStdError(hErr);
    setInheritable(hIn);
    setInheritable(hOut);
    if (!redirectErrorStream) {
        setInheritable(hErr);
    }
    try {
        ProcessCreationHelper.execute(() -> {
            String lpApplicationName = null;
            int dwCreationFlags = CREATE_SUSPENDED | DETACHED_PROCESS | HIGH_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP | CREATE_UNICODE_ENVIRONMENT | (Kernel32Util.getOSVersion() >= 0x602 ? 0 : CREATE_BREAKAWAY_FROM_JOB) | CREATE_NO_WINDOW;
            Kernel32Util.assertTrue(Advapi32.INSTANCE.CreateProcessAsUserW(hToken.getValue(), // executable name
            WString.toNative(lpApplicationName), // command line
            WString.toNative(lpCommandLine), // process security attribute
            null, // thread security attribute
            null, // inherits system handles
            true, // selected based on exe type
            dwCreationFlags, EMPTY_ENV, WString.toNative(Objects.toString(lpCurrentDirectory, null)), startupInfo, lpProcessInformation));
        });
    } catch (Win32Exception ex) {
        throw new NotExecutableException(ex);
    }
    return lpProcessInformation;
}
Also used : PROCESS_INFORMATION(jnc.platform.win32.PROCESS_INFORMATION) NotExecutableException(cn.edu.zjnu.acm.judge.core.NotExecutableException) STARTUPINFO(jnc.platform.win32.STARTUPINFO) WString(jnc.platform.win32.WString) Win32Exception(jnc.platform.win32.Win32Exception)

Example 2 with NotExecutableException

use of cn.edu.zjnu.acm.judge.core.NotExecutableException in project judge by zjnu-acm.

the class JudgeRunnerImpl method run.

@Override
public RunResult run(RunRecord runRecord, Path workDirectory, JudgeData judgeData, Validator validator, boolean cleanDirectory) {
    Objects.requireNonNull(runRecord);
    Objects.requireNonNull(workDirectory);
    try {
        RunResult.Builder builder = RunResult.builder();
        String source = runRecord.getSource();
        if (!StringUtils.hasLength(source)) {
            return builder.type(Status.COMPILATION_ERROR).compileInfo("empty source file").build();
        }
        final String main = "Main";
        Files.createDirectories(workDirectory);
        Language language = runRecord.getLanguage();
        // 源码码文件
        Path sourceFile = workDirectory.resolve(main + "." + language.getSourceExtension());
        Files.write(sourceFile, source.getBytes(Platform.getCharset()));
        String compileCommand = language.getCompileCommand();
        log.debug("Compile Command: {}", compileCommand);
        if (StringUtils.hasText(compileCommand)) {
            // create compiling process
            // VC++ will output compiling info to stdout
            // G++ will output compiling info to stderr
            Path compileInfo = workDirectory.resolve("compileInfo.txt");
            @SuppressWarnings("null") Process process = ProcessCreationHelper.execute(new ProcessBuilder(compileCommand.split("\\s+")).directory(workDirectory.toFile()).redirectInput(ProcessBuilder.Redirect.from(NULL_FILE)).redirectOutput(compileInfo.toFile()).redirectErrorStream(true)::start);
            try {
                process.waitFor(1, TimeUnit.MINUTES);
            } catch (InterruptedException ex) {
                process.destroy();
                throw new InterruptedIOException();
            }
            // export compiling information
            String errorInfo;
            if (process.isAlive()) {
                process.destroyForcibly();
                try {
                    process.waitFor();
                } catch (InterruptedException ex) {
                    throw new InterruptedIOException();
                }
                errorInfo = "Compile timeout\nOutput:\n" + collectLines(compileInfo);
            } else {
                errorInfo = collectLines(compileInfo);
            }
            builder.compileInfo(errorInfo);
            log.debug("errorInfo = {}", errorInfo);
            // The executable file after compiling
            Path executable = workDirectory.resolve(main + "." + language.getExecutableExtension());
            log.debug("executable = {}", executable);
            boolean compilePassed = Files.exists(executable);
            if (!compilePassed) {
                return builder.type(Status.COMPILATION_ERROR).build();
            }
        }
        int caseNum = judgeData.getCaseCount();
        ArrayList<String> details = new ArrayList<>(caseNum << 2);
        String command = language.getExecuteCommand();
        // executable command should be absolute
        command = StringUtils.hasText(command) ? command : workDirectory.toAbsolutePath().resolve("Main." + language.getExecutableExtension()).toString();
        long extTime = language.getExtTime();
        long castTimeLimit = runRecord.getTimeLimit() * language.getTimeFactor() + extTime;
        // 内存附加
        long extraMemory = language.getExtMemory();
        long caseMemoryLimit = (runRecord.getMemoryLimit() + extraMemory) * 1024;
        Option[] opts = new Option[caseNum];
        for (int cas = 0; cas < caseNum; cas++) {
            Path[] entry = judgeData.get(cas);
            Path in = entry[0];
            Path standard = entry[1];
            Path progOutput = workDirectory.resolve(standard.getFileName());
            opts[cas] = Option.builder().timeLimit(// time limit
            castTimeLimit).memoryLimit(// memory in bytes
            caseMemoryLimit).outputLimit(// 16M
            16 * 1024 * 1024).command(command).workDirectory(workDirectory).inputFile(in).outputFile(progOutput).standardOutput(standard).errFile(NULL_FILE.toPath()).build();
        }
        String scorePerCase = new DecimalFormat("0.#").format(100.0 / caseNum);
        final ExecuteResult[] ers;
        try {
            ers = judgeBridge.judge(opts, false, validator);
        } catch (NotExecutableException ex) {
            // original command
            if (!StringUtils.hasText(language.getExecuteCommand())) {
                String msg = "fail to execute the binary file";
                Win32Exception cause = ex.getCause();
                if (cause != null) {
                    msg = msg + ": " + cause.getMessage();
                }
                return builder.type(Status.COMPILATION_ERROR).detail(msg).build();
            }
            throw ex.getCause();
        }
        long time = 0;
        long memory = 0;
        // final case whose result is accepted.
        int accept = 0;
        for (ExecuteResult er : ers) {
            long tim1 = Math.max(0, er.getTime() - extTime);
            long mem1 = Math.max(0, er.getMemory() / 1024 - extraMemory);
            String message = er.getMessage();
            boolean success = er.isSuccess();
            time = Math.max(time, tim1);
            memory = Math.max(memory, mem1);
            log.debug("message = {}, time = {}, memory = {}", message, time, memory);
            details.add(String.valueOf(er.getCode().getResult()));
            details.add(success ? scorePerCase : "0");
            details.add(String.valueOf(tim1));
            details.add(String.valueOf(mem1));
            if (success) {
                ++accept;
            }
        }
        log.debug("{}", details);
        int score = accept >= 0 ? (int) Math.round(accept * 100.0 / caseNum) : accept;
        if (score == 0 && accept != 0) {
            ++score;
        } else if (score == 100 && accept != caseNum) {
            --score;
        }
        String msg = details.stream().map(String::valueOf).collect(Collectors.joining(","));
        return builder.score(score).time(time).memory(memory).detail(msg).build();
    } catch (IOException ex) {
        throw new UncheckedIOException(ex);
    } finally {
        if (cleanDirectory) {
            delete(workDirectory);
        }
    }
}
Also used : InterruptedIOException(java.io.InterruptedIOException) DecimalFormat(java.text.DecimalFormat) ArrayList(java.util.ArrayList) UncheckedIOException(java.io.UncheckedIOException) Language(cn.edu.zjnu.acm.judge.domain.Language) ExecuteResult(cn.edu.zjnu.acm.judge.core.ExecuteResult) RunResult(cn.edu.zjnu.acm.judge.support.RunResult) Path(java.nio.file.Path) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) Win32Exception(jnc.platform.win32.Win32Exception) NotExecutableException(cn.edu.zjnu.acm.judge.core.NotExecutableException) Option(cn.edu.zjnu.acm.judge.core.Option)

Aggregations

NotExecutableException (cn.edu.zjnu.acm.judge.core.NotExecutableException)2 Win32Exception (jnc.platform.win32.Win32Exception)2 ExecuteResult (cn.edu.zjnu.acm.judge.core.ExecuteResult)1 Option (cn.edu.zjnu.acm.judge.core.Option)1 Language (cn.edu.zjnu.acm.judge.domain.Language)1 RunResult (cn.edu.zjnu.acm.judge.support.RunResult)1 IOException (java.io.IOException)1 InterruptedIOException (java.io.InterruptedIOException)1 UncheckedIOException (java.io.UncheckedIOException)1 Path (java.nio.file.Path)1 DecimalFormat (java.text.DecimalFormat)1 ArrayList (java.util.ArrayList)1 PROCESS_INFORMATION (jnc.platform.win32.PROCESS_INFORMATION)1 STARTUPINFO (jnc.platform.win32.STARTUPINFO)1 WString (jnc.platform.win32.WString)1