Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 25 additions & 28 deletions src/judge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ impl Judge<Created> {
#[builder(default = Duration::from_secs(1))] idle_time_limit: Duration,
) -> io::Result<Judge<Created>> {
let project_path = env::temp_dir().join(Uuid::new_v4().to_string());
fs::create_dir(&project_path).await.unwrap();
fs::create_dir(&project_path).await?;

let main_path = project_path
.join(MAIN)
.with_extension(main.language.extension);
fs::write(&main_path, main.content).await.unwrap();
fs::write(&main_path, main.content).await?;
if let Some(checker) = &checker {
let mut checker_path = project_path.join(CHECKER);
if checker.language.is_interpreted() {
Expand All @@ -65,10 +65,9 @@ impl Judge<Created> {
.truncate(true)
.mode(0o755)
.open(&checker_path)
.await
.unwrap();
checker_file.write_all(checker.content).await.unwrap();
checker_file.sync_all().await.unwrap();
.await?;
checker_file.write_all(checker.content).await?;
checker_file.sync_all().await?;
}

Ok(Judge {
Expand All @@ -90,8 +89,8 @@ impl Judge {
#[switch_to(Compiled)]
pub async fn compile(self) -> io::Result<Result<Judge<Compiled>, Verdict>> {
if let Some(mut cmd) = self.language.get_compile_command(MAIN) {
let mut process = cmd.current_dir(&self.project_path).spawn().unwrap();
let status = process.wait().await.unwrap();
let mut process = cmd.current_dir(&self.project_path).spawn()?;
let status = process.wait().await?;
if !status.success() {
return Ok(Err(Verdict::CompilationError));
}
Expand Down Expand Up @@ -122,67 +121,65 @@ impl Judge {
pub async fn run(&self, input: &[u8]) -> io::Result<Metrics> {
let checker_language = self
.checker_language
.ok_or(io::Error::other("Missing checker"))
.unwrap();
.ok_or(io::Error::other("Missing checker"))?;
let mut checker = checker_language
.get_run_command(CHECKER)
.current_dir(&self.project_path)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.unwrap();
.spawn()?;
let mut cstdin = checker.stdin.take().unwrap();
let mut cstdout = checker.stdout.take().unwrap();
cstdin.write_all(input).await.unwrap();
cstdin.write_all(b"\n").await.unwrap();
cstdin.flush().await.unwrap();
cstdin.write_all(input).await?;
cstdin.write_all(b"\n").await?;
cstdin.flush().await?;

let sandbox = Sandbox::new(self.resource, self.time_limit, self.idle_time_limit).unwrap();
let sandbox = Sandbox::new(self.resource, self.time_limit, self.idle_time_limit)?;
let mut cmd = self.language.get_run_command(MAIN);
cmd.current_dir(&self.project_path)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped());
let mut main = sandbox.spawn(cmd).unwrap();
let mut main = sandbox.spawn(cmd)?;
let mut stdin = main.stdin.take().unwrap();
let mut stdout = main.stdout.take().unwrap();
let mut stderr = main.stderr.take().unwrap();

let monitor = tokio::spawn(async move { sandbox.monitor(main).await });
if !self.is_interactive {
stdin.write_all(input).await.unwrap();
stdin.write_all(b"\n").await.unwrap();
stdin.flush().await.unwrap();
stdin.write_all(input).await?;
stdin.write_all(b"\n").await?;
stdin.flush().await?;
}
let stdin_thread =
tokio::spawn(async move { tokio::io::copy(&mut cstdout, &mut stdin).await });
let stdout_thread = tokio::spawn(async move {
let mut out = vec![];
let mut buffer = [0u8; BUFFER_SIZE];
loop {
let n = stdout.read(&mut buffer).await.unwrap();
let n = stdout.read(&mut buffer).await?;
if n == 0 {
break;
}
if cstdin.write_all(&buffer[..n]).await.is_err() {
break;
}
cstdin.flush().await.unwrap();
cstdin.flush().await?;
out.extend_from_slice(&buffer[0..n]);
}

Ok::<_, io::Error>(out)
});

let (verdict, run_time, memory_usage) = monitor.await.unwrap().unwrap();
let checker_status = checker.wait().await.unwrap();
let (verdict, run_time, memory_usage) = monitor.await.unwrap()?;
let checker_status = checker.wait().await?;
drop(checker);

let _ = stdin_thread.await;
let stdout = stdout_thread.await.unwrap().unwrap();
let stdout = stdout_thread.await.unwrap()?;
let mut err = vec![];
stderr.read_to_end(&mut err).await.unwrap();
stderr.read_to_end(&mut err).await?;

if let Some(verdict) = verdict {
return Ok(Metrics {
Expand Down Expand Up @@ -221,7 +218,7 @@ impl Judge {

// running sequentially to enable early exit, saving resources
for input in inputs {
let metrics = self.run(input).await.unwrap();
let metrics = self.run(input).await?;
total_run_time += metrics.run_time;
total_memory_usage = total_memory_usage
.add(metrics.memory_usage)
Expand Down Expand Up @@ -254,7 +251,7 @@ impl Judge {

// running sequentially to enable early exit, saving resources
while let Some(input) = inputs.next().await {
let metrics = self.run(input).await.unwrap();
let metrics = self.run(input).await?;
total_run_time += metrics.run_time;
total_memory_usage = total_memory_usage
.add(metrics.memory_usage)
Expand Down
15 changes: 6 additions & 9 deletions src/sandbox/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl Sandbox {
idle_time_limit: Duration,
) -> io::Result<Sandbox> {
Ok(Sandbox {
cgroup: resource.try_into().unwrap(),
cgroup: resource.try_into()?,
cpu_usage_limit: time_limit,
wall_time_limit: Duration::max(time_limit * 2, time_limit + Duration::from_secs(2)),
idle_time_limit,
Expand All @@ -55,18 +55,15 @@ impl Sandbox {
};
self.cgroup
.add_task_by_tgid(CgroupPid::from(id as u64))
.map_err(io::Error::other)
.unwrap();
.map_err(io::Error::other)?;
let cpu: &CpuController = self
.cgroup
.controller_of()
.ok_or(io::Error::other("Missing cpu controller"))
.unwrap();
.ok_or(io::Error::other("Missing cpu controller"))?;
let memory: &MemController = self
.cgroup
.controller_of()
.ok_or(io::Error::other("Missing memory controller"))
.unwrap();
.ok_or(io::Error::other("Missing memory controller"))?;

let start = Instant::now();
let mut memory_usage = Byte::default();
Expand All @@ -75,7 +72,7 @@ impl Sandbox {

let mut interval = interval(POLL);

while child.try_wait().unwrap().is_none() {
while child.try_wait()?.is_none() {
let cpu_usage = cpu.usage();
memory_usage = memory_usage.max(memory.usage());

Expand Down Expand Up @@ -109,7 +106,7 @@ impl Sandbox {
interval.tick().await;
}

let status = child.try_wait().unwrap().unwrap();
let status = child.try_wait()?.unwrap();
if status.success() {
return Ok((None, prev_cpu_usage, memory_usage));
}
Expand Down
3 changes: 1 addition & 2 deletions src/sandbox/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ impl TryFrom<Resource> for Cgroup {

let cgroup = builder
.build(hierarchies::auto())
.map_err(io::Error::other)
.unwrap();
.map_err(io::Error::other)?;
Ok(cgroup)
}
}
Loading