@@ -8,9 +8,11 @@ use std::str;
88use std:: time:: { SystemTime , UNIX_EPOCH } ;
99use std:: {
1010 fmt:: Display ,
11+ io,
1112 io:: { BufReader , prelude:: * } ,
1213 net:: TcpListener ,
1314 thread,
15+ time:: Duration ,
1416} ;
1517
1618use crate :: { BaseConfig , Worker , WorkerError , Workload , WorkloadConfig } ;
@@ -37,6 +39,29 @@ impl NetworkWorker {
3739 }
3840 }
3941
42+ fn bind_port (
43+ & self ,
44+ addr : Ipv4Address ,
45+ target_port : u16 ,
46+ ) -> Result < TcpListener , WorkerError > {
47+ const MAX_BIND_RETRIES : usize = 30 ;
48+ let addr = addr. to_string ( ) ;
49+ for _ in 0 ..MAX_BIND_RETRIES {
50+ match TcpListener :: bind ( ( addr. as_str ( ) , target_port) ) {
51+ Ok ( l) => return Ok ( l) ,
52+ Err ( e) if e. kind ( ) == io:: ErrorKind :: AddrInUse => {
53+ thread:: sleep ( Duration :: from_secs ( 1 ) ) ;
54+ }
55+ Err ( e) => panic ! ( "Failed to bind: {}" , e) ,
56+ }
57+ }
58+
59+ Err ( WorkerError :: InternalWithMessage ( format ! (
60+ "Failed to bind {}:{} after {} retries: address in use" ,
61+ addr, target_port, MAX_BIND_RETRIES
62+ ) ) )
63+ }
64+
4065 /// Start a simple server. The client side is going to be a networking
4166 /// worker as well, so for convenience of troubleshooting do not error
4267 /// out if something unexpected happened, log and proceed instead.
@@ -47,8 +72,7 @@ impl NetworkWorker {
4772 ) -> Result < ( ) , WorkerError > {
4873 debug ! ( "Starting server at {:?}:{:?}" , addr, target_port) ;
4974
50- let listener =
51- TcpListener :: bind ( ( addr. to_string ( ) , target_port) ) . unwrap ( ) ;
75+ let listener = self . bind_port ( addr, target_port) ?;
5276
5377 for stream in listener. incoming ( ) {
5478 let mut stream = stream. unwrap ( ) ;
0 commit comments