Search in sources :

Example 1 with PROCESS_INFORMATION

use of jnc.platform.win32.PROCESS_INFORMATION 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 PROCESS_INFORMATION

use of jnc.platform.win32.PROCESS_INFORMATION in project judge by zjnu-acm.

the class WindowsExecutor method execute.

@Override
public ExecuteResult execute(Option option) throws IOException {
    Path inputFile = option.getInputFile();
    Path outputPath = option.getOutputFile();
    boolean redirectErrorStream = option.isRedirectErrorStream();
    Path errorPath = option.getErrFile();
    Path workDirectory = option.getWorkDirectory();
    String command = option.getCommand();
    long timeLimit = option.getTimeLimit();
    long memoryLimit = option.getMemoryLimit();
    long outputLimit = option.getOutputLimit();
    PROCESS_INFORMATION pi;
    try (Handle hIn = fileOpen(inputFile, Executor.O_RDONLY);
        Handle hOut = fileOpen(outputPath, Executor.O_WRONLY | Executor.O_CREAT | Executor.O_TRUNC);
        Handle hErr = redirectErrorStream ? hOut : fileOpen(errorPath, Executor.O_WRONLY | Executor.O_CREAT | Executor.O_TRUNC)) {
        pi = createProcess(command, hIn.getValue(), hOut.getValue(), hErr.getValue(), redirectErrorStream, workDirectory);
    }
    Job job;
    long process = pi.getProcess();
    try {
        job = new Job(JobLevel.JOB_RESTRICTED, null, 0, 0);
        try {
            job.assignProcessToJob(process);
        } catch (Throwable t) {
            job.close();
            throw t;
        }
    } catch (Throwable t) {
        Kernel32.INSTANCE.TerminateProcess(process, 1);
        throw t;
    }
    try (Handle hProcess = Handle.of(process);
        Handle hThread = Handle.of(pi.getThread())) {
        JudgeProcess judgeProcess = new JudgeProcess(hProcess.getValue());
        try (FileChannel cOut = FileChannel.open(outputPath);
            FileChannel cErr = redirectErrorStream ? cOut : FileChannel.open(errorPath)) {
            int dwCount = Kernel32.INSTANCE.ResumeThread(hThread.getValue());
            Kernel32Util.assertTrue(dwCount != -1);
            hThread.close();
            Instant startTime = judgeProcess.getStartTime();
            while (true) {
                long memory = judgeProcess.getPeakMemory();
                if (memory > memoryLimit) {
                    judgeProcess.terminate(Status.MEMORY_LIMIT_EXCEED);
                    judgeProcess.join(Constants.TERMINATE_TIMEOUT);
                    break;
                }
                // extra 5 seconds
                long time = ChronoUnit.MILLIS.between(startTime, Instant.now()) - 5000;
                if (time > timeLimit || judgeProcess.getTime() > timeLimit) {
                    judgeProcess.terminate(Status.TIME_LIMIT_EXCEED);
                    judgeProcess.join(Constants.TERMINATE_TIMEOUT);
                    break;
                }
                long dwWaitTime = timeLimit - time;
                if (dwWaitTime > Constants.UPDATE_TIME_THRESHOLD) {
                    dwWaitTime = Constants.UPDATE_TIME_THRESHOLD;
                }
                if (judgeProcess.join(dwWaitTime)) {
                    break;
                }
                if (checkOle(cOut, cErr, redirectErrorStream, outputLimit)) {
                    judgeProcess.terminate(Status.OUTPUT_LIMIT_EXCEED);
                    judgeProcess.join(Constants.TERMINATE_TIMEOUT);
                    break;
                }
            }
            if (checkOle(cOut, cErr, redirectErrorStream, outputLimit)) {
                judgeProcess.terminate(Status.OUTPUT_LIMIT_EXCEED);
            }
        } finally {
            judgeProcess.terminate(Status.ACCEPTED);
        }
        judgeProcess.join(Long.MAX_VALUE);
        Status status = judgeProcess.getStatus();
        int exitCode = judgeProcess.getExitCode();
        if (status == Status.ACCEPTED && exitCode != 0) {
            status = Status.RUNTIME_ERROR;
        }
        long time = judgeProcess.getTime();
        if (status == Status.TIME_LIMIT_EXCEED) {
            time = ((time - timeLimit - 1) % 200 + 200) % 200 + 1 + timeLimit;
        }
        return ExecuteResult.builder().time(time).memory(judgeProcess.getPeakMemory()).code(status).exitCode(exitCode).build();
    } finally {
        job.close();
    }
}
Also used : Path(java.nio.file.Path) Status(cn.edu.zjnu.acm.judge.core.Status) FileChannel(java.nio.channels.FileChannel) Instant(java.time.Instant) WString(jnc.platform.win32.WString) Handle(jnc.platform.win32.Handle) PROCESS_INFORMATION(jnc.platform.win32.PROCESS_INFORMATION)

Aggregations

PROCESS_INFORMATION (jnc.platform.win32.PROCESS_INFORMATION)2 WString (jnc.platform.win32.WString)2 NotExecutableException (cn.edu.zjnu.acm.judge.core.NotExecutableException)1 Status (cn.edu.zjnu.acm.judge.core.Status)1 FileChannel (java.nio.channels.FileChannel)1 Path (java.nio.file.Path)1 Instant (java.time.Instant)1 Handle (jnc.platform.win32.Handle)1 STARTUPINFO (jnc.platform.win32.STARTUPINFO)1 Win32Exception (jnc.platform.win32.Win32Exception)1