@@ -401,7 +401,9 @@ impl Server {
401
401
let reaper_tx_child = reaper_tx. clone ( ) ;
402
402
let pipe_connection_child = pipe_connection. clone ( ) ;
403
403
404
- let handler = thread:: Builder :: new ( )
404
+ let ( sync_tx, sync_rx) = channel ( ) ;
405
+
406
+ let _ = thread:: Builder :: new ( )
405
407
. name ( "client_handler" . into ( ) )
406
408
. spawn ( move || {
407
409
debug ! ( "Got new client" ) ;
@@ -505,25 +507,38 @@ impl Server {
505
507
drop ( workload_rx) ;
506
508
handler. join ( ) . unwrap_or ( ( ) ) ;
507
509
reader. join ( ) . unwrap_or ( ( ) ) ;
510
+
511
+ //wait untile this connection had been inserted connections map;
512
+ sync_rx. recv ( ) . unwrap_or ( ( ) ) ;
513
+
508
514
// client_handler should not close fd before exit
509
515
// , which prevent fd reuse issue.
510
516
reaper_tx_child. send ( pipe. id ( ) ) . unwrap ( ) ;
511
517
512
518
debug ! ( "client thread quit" ) ;
513
519
} )
514
- . unwrap ( ) ;
515
-
516
- let mut cns = connections. lock ( ) . unwrap ( ) ;
517
-
518
- let id = pipe_connection. id ( ) ;
519
- cns. insert (
520
- id,
521
- Connection {
522
- connection : pipe_connection,
523
- handler : Some ( handler) ,
524
- quit : quit. clone ( ) ,
525
- } ,
526
- ) ;
520
+ . map ( |handler| {
521
+ let mut cns = connections. lock ( ) . unwrap ( ) ;
522
+ let id = pipe_connection. id ( ) ;
523
+ cns. insert (
524
+ id,
525
+ Connection {
526
+ connection : pipe_connection,
527
+ handler : Some ( handler) ,
528
+ quit : quit. clone ( ) ,
529
+ } ,
530
+ ) ;
531
+
532
+ // We need to ensure that only when the connection is successfully inserted into the
533
+ // connections map can the handler send fd to notify the reaper to recycle the connection.
534
+ // Otherwise, the handler may have been executed and sent fd to notify the reaper to recycle
535
+ // the connection, and the connection has not been inserted into the map. Then the reaper cannot
536
+ // find the corresponding connection after receiving the fd, and loses the opportunity to recycle
537
+ // the connection, causing fd leakage;
538
+ // Notify the handler continue, to send fd to reaper thread.
539
+ sync_tx. send ( ( ) ) . unwrap_or ( ( ) ) ;
540
+ } )
541
+ . map_err ( |e| warn ! ( "spawn handler thread failed with: {:?}" , e) ) ;
527
542
} // end loop
528
543
529
544
// notify reaper thread to exit.
0 commit comments