@@ -556,6 +556,22 @@ mod tests {
556556 }
557557 }
558558
559+ fn make_tcp_connection ( ) -> ( std:: net:: TcpStream , std:: net:: TcpStream ) {
560+ if let Ok ( listener) = std:: net:: TcpListener :: bind ( "127.0.0.1:9735" ) {
561+ ( std:: net:: TcpStream :: connect ( "127.0.0.1:9735" ) . unwrap ( ) , listener. accept ( ) . unwrap ( ) . 0 )
562+ } else if let Ok ( listener) = std:: net:: TcpListener :: bind ( "127.0.0.1:19735" ) {
563+ ( std:: net:: TcpStream :: connect ( "127.0.0.1:19735" ) . unwrap ( ) , listener. accept ( ) . unwrap ( ) . 0 )
564+ } else if let Ok ( listener) = std:: net:: TcpListener :: bind ( "127.0.0.1:9997" ) {
565+ ( std:: net:: TcpStream :: connect ( "127.0.0.1:9997" ) . unwrap ( ) , listener. accept ( ) . unwrap ( ) . 0 )
566+ } else if let Ok ( listener) = std:: net:: TcpListener :: bind ( "127.0.0.1:9998" ) {
567+ ( std:: net:: TcpStream :: connect ( "127.0.0.1:9998" ) . unwrap ( ) , listener. accept ( ) . unwrap ( ) . 0 )
568+ } else if let Ok ( listener) = std:: net:: TcpListener :: bind ( "127.0.0.1:9999" ) {
569+ ( std:: net:: TcpStream :: connect ( "127.0.0.1:9999" ) . unwrap ( ) , listener. accept ( ) . unwrap ( ) . 0 )
570+ } else if let Ok ( listener) = std:: net:: TcpListener :: bind ( "127.0.0.1:46926" ) {
571+ ( std:: net:: TcpStream :: connect ( "127.0.0.1:46926" ) . unwrap ( ) , listener. accept ( ) . unwrap ( ) . 0 )
572+ } else { panic ! ( "Failed to bind to v4 localhost on common ports" ) ; }
573+ }
574+
559575 async fn do_basic_connection_test ( ) {
560576 let secp_ctx = Secp256k1 :: new ( ) ;
561577 let a_key = SecretKey :: from_slice ( & [ 1 ; 32 ] ) . unwrap ( ) ;
@@ -595,13 +611,7 @@ mod tests {
595611 // address. This may not always be the case in containers and the like, so if this test is
596612 // failing for you check that you have a loopback interface and it is configured with
597613 // 127.0.0.1.
598- let ( conn_a, conn_b) = if let Ok ( listener) = std:: net:: TcpListener :: bind ( "127.0.0.1:9735" ) {
599- ( std:: net:: TcpStream :: connect ( "127.0.0.1:9735" ) . unwrap ( ) , listener. accept ( ) . unwrap ( ) . 0 )
600- } else if let Ok ( listener) = std:: net:: TcpListener :: bind ( "127.0.0.1:9999" ) {
601- ( std:: net:: TcpStream :: connect ( "127.0.0.1:9999" ) . unwrap ( ) , listener. accept ( ) . unwrap ( ) . 0 )
602- } else if let Ok ( listener) = std:: net:: TcpListener :: bind ( "127.0.0.1:46926" ) {
603- ( std:: net:: TcpStream :: connect ( "127.0.0.1:46926" ) . unwrap ( ) , listener. accept ( ) . unwrap ( ) . 0 )
604- } else { panic ! ( "Failed to bind to v4 localhost on common ports" ) ; } ;
614+ let ( conn_a, conn_b) = make_tcp_connection ( ) ;
605615
606616 let fut_a = super :: setup_outbound ( Arc :: clone ( & a_manager) , b_pub, conn_a) ;
607617 let fut_b = super :: setup_inbound ( b_manager, conn_b) ;
@@ -629,8 +639,53 @@ mod tests {
629639 async fn basic_threaded_connection_test ( ) {
630640 do_basic_connection_test ( ) . await ;
631641 }
642+
632643 #[ tokio:: test]
633644 async fn basic_unthreaded_connection_test ( ) {
634645 do_basic_connection_test ( ) . await ;
635646 }
647+
648+ async fn race_disconnect_accept ( ) {
649+ // Previously, if we handed an already-disconnected socket to `setup_inbound` we'd panic.
650+ // This attempts to find other similar races by opening connections and shutting them down
651+ // while connecting. Sadly in testing this did *not* reproduce the previous issue.
652+ let secp_ctx = Secp256k1 :: new ( ) ;
653+ let a_key = SecretKey :: from_slice ( & [ 1 ; 32 ] ) . unwrap ( ) ;
654+ let b_key = SecretKey :: from_slice ( & [ 2 ; 32 ] ) . unwrap ( ) ;
655+ let b_pub = PublicKey :: from_secret_key ( & secp_ctx, & b_key) ;
656+
657+ let a_manager = Arc :: new ( PeerManager :: new ( MessageHandler {
658+ chan_handler : Arc :: new ( lightning:: ln:: peer_handler:: ErroringMessageHandler :: new ( ) ) ,
659+ route_handler : Arc :: new ( lightning:: ln:: peer_handler:: IgnoringMessageHandler { } ) ,
660+ } , a_key, & [ 1 ; 32 ] , Arc :: new ( TestLogger ( ) ) , Arc :: new ( lightning:: ln:: peer_handler:: IgnoringMessageHandler { } ) ) ) ;
661+
662+ // Make two connections, one for an inbound and one for an outbound connection
663+ let conn_a = {
664+ let ( conn_a, _) = make_tcp_connection ( ) ;
665+ conn_a
666+ } ;
667+ let conn_b = {
668+ let ( _, conn_b) = make_tcp_connection ( ) ;
669+ conn_b
670+ } ;
671+
672+ // Call connection setup inside new tokio tasks.
673+ let manager_reference = Arc :: clone ( & a_manager) ;
674+ tokio:: spawn ( async move {
675+ super :: setup_inbound ( manager_reference, conn_a) . await
676+ } ) ;
677+ tokio:: spawn ( async move {
678+ super :: setup_outbound ( a_manager, b_pub, conn_b) . await
679+ } ) ;
680+ }
681+
682+ #[ tokio:: test( flavor = "multi_thread" ) ]
683+ async fn threaded_race_disconnect_accept ( ) {
684+ race_disconnect_accept ( ) . await ;
685+ }
686+
687+ #[ tokio:: test]
688+ async fn unthreaded_race_disconnect_accept ( ) {
689+ race_disconnect_accept ( ) . await ;
690+ }
636691}
0 commit comments