@@ -13,7 +13,7 @@ use bon::bon;
1313use state_shift:: { impl_state, type_state} ;
1414use uuid:: Uuid ;
1515
16- use crate :: { Language , Resource , Sandbox , Verdict } ;
16+ use crate :: { Language , Metrics , Resource , Sandbox , Verdict } ;
1717
1818const MAIN : & str = "main" ;
1919const 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
173200fn 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