@@ -63,27 +63,25 @@ impl DendriteInstance {
6363 args. push ( socket_addr. to_string ( ) ) ;
6464 }
6565
66- let child = tokio:: process:: Command :: new ( "dpd" )
66+ let mut child = tokio:: process:: Command :: new ( "dpd" )
6767 . args ( & args)
6868 . stdin ( Stdio :: null ( ) )
6969 . stdout ( Stdio :: from ( redirect_file (
7070 temp_dir. path ( ) ,
7171 "dendrite_stdout" ,
7272 ) ?) )
73- . stderr ( Stdio :: from ( redirect_file (
74- temp_dir. path ( ) ,
75- "dendrite_stderr" ,
76- ) ?) )
73+ . stderr ( Stdio :: piped ( ) )
7774 . spawn ( )
7875 . with_context ( || {
7976 format ! ( "failed to spawn `dpd` (with args: {:?})" , & args)
8077 } ) ?;
81-
82- let child = Some ( child) ;
78+ let stderr = child. stderr . take ( ) . unwrap ( ) ;
8379
8480 let temp_dir = temp_dir. keep ( ) ;
8581 if port == 0 {
8682 port = discover_port (
83+ & mut child,
84+ stderr,
8785 temp_dir. join ( "dendrite_stdout" ) . display ( ) . to_string ( ) ,
8886 )
8987 . await
@@ -95,7 +93,7 @@ impl DendriteInstance {
9593 } ) ?;
9694 }
9795
98- Ok ( Self { port, args, child, data_dir : Some ( temp_dir) } )
96+ Ok ( Self { port, args, child : Some ( child ) , data_dir : Some ( temp_dir) } )
9997 }
10098
10199 pub async fn cleanup ( & mut self ) -> Result < ( ) , anyhow:: Error > {
@@ -145,20 +143,45 @@ fn redirect_file(
145143 . with_context ( || format ! ( "open \" {}\" " , out_path. display( ) ) )
146144}
147145
148- async fn discover_port ( logfile : String ) -> Result < u16 , anyhow:: Error > {
146+ async fn discover_port (
147+ child : & mut tokio:: process:: Child ,
148+ stderr : tokio:: process:: ChildStderr ,
149+ logfile : String ,
150+ ) -> Result < u16 , anyhow:: Error > {
149151 let timeout = Instant :: now ( ) + DENDRITE_TIMEOUT ;
150- tokio:: time:: timeout_at ( timeout, find_dendrite_port_in_log ( logfile) )
151- . await
152- . context ( "time out while discovering dendrite port number" ) ?
152+ tokio:: time:: timeout_at (
153+ timeout,
154+ find_dendrite_port_in_log ( child, stderr, logfile) ,
155+ )
156+ . await
157+ . context ( "time out while discovering dendrite port number" ) ?
153158}
154159
155160async fn find_dendrite_port_in_log (
161+ child : & mut tokio:: process:: Child ,
162+ mut stderr : tokio:: process:: ChildStderr ,
156163 logfile : String ,
157164) -> Result < u16 , anyhow:: Error > {
158165 let re = regex:: Regex :: new ( r#""local_addr":"\[::1\]:([0-9]+)""# ) . unwrap ( ) ;
159166 let mut reader = BufReader :: new ( File :: open ( & logfile) . await ?) ;
160167 let mut lines = reader. lines ( ) ;
161168 loop {
169+ // Exit early if the process has exited.
170+ if let Some ( exit_status) = child. try_wait ( ) ? {
171+ let mut stderr_contents = String :: new ( ) ;
172+ tokio:: io:: AsyncReadExt :: read_to_string (
173+ & mut stderr,
174+ & mut stderr_contents,
175+ )
176+ . await ?;
177+
178+ anyhow:: bail!(
179+ "dpd exited with status {} before port could be discovered: {}" ,
180+ exit_status,
181+ stderr_contents
182+ ) ;
183+ }
184+
162185 match lines. next_line ( ) . await ? {
163186 Some ( line) => {
164187 if let Some ( cap) = re. captures ( & line) {
@@ -212,10 +235,22 @@ mod tests {
212235 writeln ! ( file, "Another garbage line" ) . unwrap ( ) ;
213236 file. flush ( ) . unwrap ( ) ;
214237
238+ let mut child = tokio:: process:: Command :: new ( "dpd" )
239+ . stdin ( Stdio :: null ( ) )
240+ . stdout ( Stdio :: null ( ) )
241+ . stderr ( Stdio :: piped ( ) )
242+ . spawn ( )
243+ . unwrap ( ) ;
244+ let stderr = child. stderr . take ( ) . unwrap ( ) ;
245+
215246 assert_eq ! (
216- find_dendrite_port_in_log( file. path( ) . display( ) . to_string( ) )
217- . await
218- . unwrap( ) ,
247+ find_dendrite_port_in_log(
248+ & mut child,
249+ stderr,
250+ file. path( ) . display( ) . to_string( )
251+ )
252+ . await
253+ . unwrap( ) ,
219254 EXPECTED_PORT
220255 ) ;
221256 }
0 commit comments