Skip to content

Commit 8707bd6

Browse files
committed
feat(judge): return metrics, spawn thread in scope
1 parent c4ff349 commit 8707bd6

1 file changed

Lines changed: 60 additions & 31 deletions

File tree

src/judge.rs

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use bon::bon;
1313
use state_shift::{impl_state, type_state};
1414
use uuid::Uuid;
1515

16-
use crate::{Language, Resource, Sandbox, Verdict};
16+
use crate::{Language, Metrics, Resource, Sandbox, Verdict};
1717

1818
const MAIN: &str = "main";
1919
const CHECKER: &str = "checker";
@@ -113,7 +113,7 @@ impl Judge {
113113
is_interactive: bool,
114114
resource: Resource,
115115
time_limit: Duration,
116-
) -> io::Result<Verdict> {
116+
) -> io::Result<Metrics> {
117117
let Judge {
118118
project_path,
119119
language,
@@ -127,36 +127,57 @@ impl Judge {
127127
.current_dir(&project_path)
128128
.stdin(Stdio::piped())
129129
.stdout(Stdio::piped())
130+
.stderr(Stdio::null())
130131
.spawn()?;
131-
let mut cin = checker.stdin.take().unwrap();
132-
let cout = checker.stdout.take().unwrap();
132+
let mut cstdin = checker.stdin.take().unwrap();
133+
let cstdout = checker.stdout.take().unwrap();
133134

134135
let sandbox = Sandbox::new(resource, time_limit)?;
135-
let mut submission_command = language.get_run_command(MAIN);
136-
submission_command
137-
.current_dir(&project_path)
136+
let mut cmd = language.get_run_command(MAIN);
137+
cmd.current_dir(&project_path)
138138
.stdin(Stdio::piped())
139-
.stdout(Stdio::piped());
140-
let mut submission = sandbox.spawn(submission_command)?;
141-
let mut sin = submission.stdin.take().unwrap();
142-
let sout = submission.stdout.take().unwrap();
143-
144-
let monitor_thread = thread::spawn(move || sandbox.monitor(submission));
145-
146-
if !is_interactive {
147-
sin.write_all(input)?;
148-
sin.write_all(b"\n")?;
149-
sin.flush()?;
150-
}
151-
cin.write_all(input)?;
152-
cin.write_all(b"\n")?;
153-
cin.flush()?;
154-
155-
forward(cout, sin);
156-
forward(sout, cin);
157-
158-
if let Some(verdict) = monitor_thread.join().unwrap()? {
159-
return Ok(verdict);
139+
.stdout(Stdio::piped())
140+
.stderr(Stdio::piped());
141+
let mut main = sandbox.spawn(cmd)?;
142+
let mut stdin = main.stdin.take().unwrap();
143+
let stdout = main.stdout.take().unwrap();
144+
let mut stderr = main.stderr.take().unwrap();
145+
146+
let ((verdict, run_time, memory_usage), stdout) = thread::scope(|scope| {
147+
let monitor_thread = scope.spawn(|| sandbox.monitor(main));
148+
149+
if !is_interactive {
150+
stdin.write_all(input)?;
151+
stdin.write_all(b"\n")?;
152+
stdin.flush()?;
153+
}
154+
cstdin.write_all(input)?;
155+
cstdin.write_all(b"\n")?;
156+
cstdin.flush()?;
157+
158+
forward(cstdout, stdin);
159+
let main_to_checker = forward(stdout, cstdin);
160+
161+
let monitor_result = match monitor_thread.join().unwrap() {
162+
Ok(v) => v,
163+
Err(err) => return Err(err),
164+
};
165+
let output = main_to_checker.join().unwrap()?;
166+
let output = String::from_utf8(output).map_err(io::Error::other)?;
167+
168+
Ok((monitor_result, output))
169+
})?;
170+
let mut err = String::new();
171+
stderr.read_to_string(&mut err)?;
172+
173+
if let Some(verdict) = verdict {
174+
return Ok(Metrics {
175+
verdict,
176+
run_time,
177+
stdout,
178+
stderr: err,
179+
memory_usage,
180+
});
160181
}
161182

162183
let status = checker.wait()?;
@@ -166,26 +187,34 @@ impl Judge {
166187
Verdict::WrongAnswer
167188
};
168189

169-
Ok(verdict)
190+
Ok(Metrics {
191+
verdict,
192+
run_time,
193+
stdout,
194+
stderr: err,
195+
memory_usage,
196+
})
170197
}
171198
}
172199

173200
fn forward<R: Read + Send + 'static, W: Write + Send + 'static>(
174201
mut reader: R,
175202
mut writer: W,
176-
) -> thread::JoinHandle<io::Result<()>> {
203+
) -> thread::JoinHandle<io::Result<Vec<u8>>> {
177204
thread::spawn(move || {
205+
let mut stdout: Vec<u8> = vec![];
178206
let mut buffer = [0u8; BUFFER_SIZE];
179207
loop {
180208
let n = reader.read(&mut buffer)?;
181209
if n == 0 {
182210
drop(writer);
183211
break;
184212
}
213+
stdout.extend_from_slice(&buffer[0..n]);
185214
writer.write_all(&buffer[..n])?;
186215
writer.flush()?;
187216
}
188217

189-
Ok(())
218+
Ok(stdout)
190219
})
191220
}

0 commit comments

Comments
 (0)