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;
}
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();
}
}
Aggregations