@@ -61,36 +61,49 @@ pub fn run(server: &SocketAddr, shell: &Shell, timeout: u64) -> Result<(), Error
61
61
let driver_url = match driver. location ( ) {
62
62
Locate :: Remote ( url) => Ok ( url. clone ( ) ) ,
63
63
Locate :: Local ( ( path, args) ) => {
64
- // Allow tests to run in parallel (in theory) by finding any open port
65
- // available for our driver. We can't bind the port for the driver, but
66
- // hopefully the OS gives this invocation unique ports across processes
67
- let driver_addr = TcpListener :: bind ( "127.0.0.1:0" ) ?. local_addr ( ) ?;
68
-
69
- // Spawn the driver binary, collecting its stdout/stderr in separate
70
- // threads. We'll print this output later.
71
- let mut cmd = Command :: new ( path) ;
72
- cmd. args ( args) . arg ( format ! ( "--port={}" , driver_addr. port( ) ) ) ;
73
- let mut child = BackgroundChild :: spawn ( path, & mut cmd, shell) ?;
74
- drop_log = Box :: new ( move || {
75
- let _ = & child;
76
- child. print_stdio_on_drop = false ;
77
- } ) ;
78
-
79
64
// Wait for the driver to come online and bind its port before we try to
80
65
// connect to it.
81
66
let start = Instant :: now ( ) ;
82
67
let max = Duration :: new ( 5 , 0 ) ;
83
- let mut bound = false ;
84
- while start. elapsed ( ) < max {
85
- if TcpStream :: connect ( driver_addr) . is_ok ( ) {
86
- bound = true ;
87
- break ;
68
+
69
+ let ( driver_addr, mut child) = ' outer: loop {
70
+ // Allow tests to run in parallel (in theory) by finding any open port
71
+ // available for our driver. We can't bind the port for the driver, but
72
+ // hopefully the OS gives this invocation unique ports across processes
73
+ let driver_addr = TcpListener :: bind ( "127.0.0.1:0" ) ?. local_addr ( ) ?;
74
+ // Spawn the driver binary, collecting its stdout/stderr in separate
75
+ // threads. We'll print this output later.
76
+ let mut cmd = Command :: new ( path) ;
77
+ cmd. args ( args) . arg ( format ! ( "--port={}" , driver_addr. port( ) ) ) ;
78
+ let mut child = BackgroundChild :: spawn ( path, & mut cmd, shell) ?;
79
+
80
+ // Wait for the driver to come online and bind its port before we try to
81
+ // connect to it.
82
+ loop {
83
+ if child. has_failed ( ) {
84
+ if start. elapsed ( ) >= max {
85
+ bail ! ( "driver failed to start" )
86
+ }
87
+
88
+ println ! ( "Failed to start driver, trying again ..." ) ;
89
+
90
+ thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
91
+ break ;
92
+ } else if TcpStream :: connect ( driver_addr) . is_ok ( ) {
93
+ break ' outer ( driver_addr, child) ;
94
+ } else if start. elapsed ( ) >= max {
95
+ bail ! ( "driver failed to bind port during startup" )
96
+ } else {
97
+ thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
98
+ }
88
99
}
89
- thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
90
- }
91
- if !bound {
92
- bail ! ( "driver failed to bind port during startup" )
93
- }
100
+ } ;
101
+
102
+ drop_log = Box :: new ( move || {
103
+ let _ = & child;
104
+ child. print_stdio_on_drop = false ;
105
+ } ) ;
106
+
94
107
Url :: parse ( & format ! ( "http://{}" , driver_addr) ) . map_err ( Error :: from)
95
108
}
96
109
} ?;
@@ -646,6 +659,14 @@ impl<'a> BackgroundChild<'a> {
646
659
print_stdio_on_drop : true ,
647
660
} )
648
661
}
662
+
663
+ fn has_failed ( & mut self ) -> bool {
664
+ match self . child . try_wait ( ) {
665
+ Ok ( Some ( status) ) => !status. success ( ) ,
666
+ Ok ( None ) => false ,
667
+ Err ( _) => true ,
668
+ }
669
+ }
649
670
}
650
671
651
672
impl < ' a > Drop for BackgroundChild < ' a > {
0 commit comments