@@ -33,6 +33,9 @@ fn listen(host: String, port: u16, timeout_nanos: u64) -> io::Result<Listener> {
3333 socket2:: Type :: STREAM ,
3434 Some ( socket2:: Protocol :: TCP ) ,
3535 ) ?;
36+ // Allow a server restart while its previous connections are in TIME_WAIT.
37+ #[ cfg( unix) ]
38+ socket. set_reuse_address ( true ) ?;
3639 #[ cfg( windows) ]
3740 exclusive_address ( & socket) ?;
3841 socket. bind ( & address. into ( ) ) ?;
@@ -260,6 +263,38 @@ mod tests {
260263 assert ! ( matches!( listener. socket( ) , Err ( ListenerError :: Closed ) ) ) ;
261264 }
262265
266+ #[ cfg( unix) ]
267+ #[ test]
268+ fn can_listen_again_while_previous_connection_is_in_time_wait ( ) {
269+ use std:: { io:: Read , net:: Shutdown } ;
270+
271+ let listener = listen ( "127.0.0.1" . into ( ) , 0 , LONG ) . unwrap ( ) ;
272+ let address = listener
273+ . socket ( )
274+ . unwrap ( )
275+ . local_addr ( )
276+ . unwrap ( )
277+ . as_socket ( )
278+ . unwrap ( ) ;
279+ let mut client = TcpStream :: connect ( address) . unwrap ( ) ;
280+ let mut server = listener. accept ( Some ( LONG ) ) . unwrap ( ) ;
281+ server. set_nonblocking ( false ) . unwrap ( ) ;
282+ let timeout = Some ( Duration :: from_nanos ( LONG ) ) ;
283+ client. set_read_timeout ( timeout) . unwrap ( ) ;
284+ server. set_read_timeout ( timeout) . unwrap ( ) ;
285+
286+ // The server sends the first FIN and enters TIME_WAIT when it receives the client's FIN.
287+ let mut byte = [ 0 ] ;
288+ server. shutdown ( Shutdown :: Write ) . unwrap ( ) ;
289+ assert_eq ! ( client. read( & mut byte) . unwrap( ) , 0 ) ;
290+ client. shutdown ( Shutdown :: Write ) . unwrap ( ) ;
291+ assert_eq ! ( server. read( & mut byte) . unwrap( ) , 0 ) ;
292+ drop ( ( server, client, listener) ) ;
293+
294+ listen ( "127.0.0.1" . into ( ) , address. port ( ) , LONG )
295+ . expect ( "could not restart listener with a connection in TIME_WAIT" ) ;
296+ }
297+
263298 #[ test]
264299 fn accept_without_a_timeout_waits_for_a_client ( ) {
265300 let listener = listen ( "127.0.0.1" . into ( ) , 0 , LONG ) . unwrap ( ) ;
0 commit comments