@@ -10,28 +10,34 @@ use std::{
1010} ;
1111
1212use byte_unit:: Byte ;
13- use cgroups_rs:: { CgroupPid , fs:: Cgroup } ;
13+ use cgroups_rs:: {
14+ CgroupPid ,
15+ fs:: { Cgroup , cpu:: CpuController , memory:: MemController } ,
16+ } ;
1417use nix:: { libc:: getpid, sys:: signal:: Signal } ;
1518pub use resource:: Resource ;
1619
17- use crate :: { Verdict , sandbox:: cgroup:: CgroupExt } ;
20+ use crate :: {
21+ Verdict ,
22+ sandbox:: cgroup:: { CpuControllerExt , MemControllerExt } ,
23+ } ;
1824
1925// TODO: need further tuning
2026const POLL : Duration = Duration :: from_millis ( 10 ) ;
21- const MIN_CPU_TIME_PER_POLL : Duration = Duration :: from_millis ( 1 ) ;
27+ const MIN_CPU_USAGE_PER_POLL : Duration = Duration :: from_millis ( 1 ) ;
2228const IDLE_TIME_LIMIT : Duration = Duration :: from_millis ( 100 ) ;
2329
2430pub struct Sandbox {
2531 pub cgroup : Cgroup ,
26- pub cpu_time_limit : Duration ,
32+ pub cpu_usage_limit : Duration ,
2733 pub wall_time_limit : Duration ,
2834}
2935
3036impl Sandbox {
3137 pub fn new ( resource : Resource , time_limit : Duration ) -> io:: Result < Sandbox > {
3238 Ok ( Sandbox {
3339 cgroup : resource. try_into ( ) ?,
34- cpu_time_limit : time_limit,
40+ cpu_usage_limit : time_limit,
3541 wall_time_limit : Duration :: max ( time_limit * 2 , time_limit + Duration :: from_secs ( 2 ) ) ,
3642 } )
3743 }
@@ -56,23 +62,31 @@ impl Sandbox {
5662 self . cgroup
5763 . add_task_by_tgid ( CgroupPid :: from ( child. id ( ) as u64 ) )
5864 . map_err ( io:: Error :: other) ?;
65+ let cpu: & CpuController = self
66+ . cgroup
67+ . controller_of ( )
68+ . ok_or ( io:: Error :: other ( "Missing cpu controller" ) ) ?;
69+ let memory: & MemController = self
70+ . cgroup
71+ . controller_of ( )
72+ . ok_or ( io:: Error :: other ( "Missing memory controller" ) ) ?;
5973
6074 let start = Instant :: now ( ) ;
6175 let mut memory_usage = Byte :: default ( ) ;
62- let mut prev_cpu_time = self . cgroup . get_cpu_time ( ) ;
76+ let mut prev_cpu_usage = cpu . usage ( ) ;
6377 let mut idle_start: Option < Instant > = None ;
6478
6579 while child. try_wait ( ) ?. is_none ( ) {
66- let cpu_time = self . cgroup . get_cpu_time ( ) ;
67- memory_usage = memory_usage. max ( self . cgroup . get_memory_usage ( ) ) ;
80+ let cpu_usage = cpu . usage ( ) ;
81+ memory_usage = memory_usage. max ( memory . usage ( ) ) ;
6882
69- if cpu_time . abs_diff ( prev_cpu_time ) <= MIN_CPU_TIME_PER_POLL {
83+ if cpu_usage . abs_diff ( prev_cpu_usage ) <= MIN_CPU_USAGE_PER_POLL {
7084 match idle_start {
7185 Some ( idle_start) => {
7286 if idle_start. elapsed ( ) >= IDLE_TIME_LIMIT {
7387 return Ok ( (
7488 Some ( Verdict :: IdleTimeLimitExceeded ) ,
75- cpu_time ,
89+ cpu_usage ,
7690 memory_usage,
7791 ) ) ;
7892 }
@@ -83,41 +97,37 @@ impl Sandbox {
8397 idle_start = None ;
8498 }
8599
86- if cpu_time >= self . cpu_time_limit || start. elapsed ( ) >= self . wall_time_limit {
100+ if cpu_usage >= self . cpu_usage_limit || start. elapsed ( ) >= self . wall_time_limit {
87101 return Ok ( (
88102 Some ( Verdict :: TimeLimitExceeded ) ,
89- self . cpu_time_limit ,
103+ self . cpu_usage_limit ,
90104 memory_usage,
91105 ) ) ;
92106 }
93107
94- prev_cpu_time = cpu_time ;
108+ prev_cpu_usage = cpu_usage ;
95109
96110 sleep ( POLL ) ;
97111 }
98112
99- // SAFETY: child must be finished at this point to exit the previous loop
100113 let status = child. try_wait ( ) ?. unwrap ( ) ;
101114 if status. success ( ) {
102- return Ok ( ( None , prev_cpu_time , memory_usage) ) ;
115+ return Ok ( ( None , prev_cpu_usage , memory_usage) ) ;
103116 }
104117 match status. signal ( ) . and_then ( |x| Signal :: try_from ( x) . ok ( ) ) {
105118 Some ( Signal :: SIGKILL ) => Ok ( (
106119 Some ( Verdict :: MemoryLimitExceeded ) ,
107- prev_cpu_time ,
108- self . cgroup . get_memory_limit ( ) ,
120+ prev_cpu_usage ,
121+ memory . limit ( ) ,
109122 ) ) ,
110- _ => Ok ( ( Some ( Verdict :: RuntimeError ) , prev_cpu_time , memory_usage) ) ,
123+ _ => Ok ( ( Some ( Verdict :: RuntimeError ) , prev_cpu_usage , memory_usage) ) ,
111124 }
112125 }
113126}
114127
115128impl Drop for Sandbox {
116129 fn drop ( & mut self ) {
117- // SAFETY: always be used with stable version of linux kernel
118130 let _ = self . cgroup . kill ( ) ;
119-
120- // SAFETY: no descendant is created previously by judge
121131 let _ = self . cgroup . delete ( ) ;
122132 }
123133}
0 commit comments