Skip to content

Commit 370459c

Browse files
author
Fupan Li
committed
sync: fix the connection fd leak on the server side
We need to ensure that only when the connection is successfully inserted into the connections map can the handler send fd to notify the reaper to recycle the connection. Otherwise, the handler may have been executed and sent fd to notify the reaper to recycle the connection, and the connection has not been inserted into the map. Then the reaper cannot find the corresponding connection after receiving the fd, and loses the opportunity to recycle the connection, causing fd leakage; Signed-off-by: Fupan Li <fupan.lfp@antgroup.com>
1 parent 4929e90 commit 370459c

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

src/sync/server.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,9 @@ impl Server {
401401
let reaper_tx_child = reaper_tx.clone();
402402
let pipe_connection_child = pipe_connection.clone();
403403

404-
let handler = thread::Builder::new()
404+
let (sync_tx, sync_rx) = channel();
405+
406+
let _ = thread::Builder::new()
405407
.name("client_handler".into())
406408
.spawn(move || {
407409
debug!("Got new client");
@@ -505,25 +507,38 @@ impl Server {
505507
drop(workload_rx);
506508
handler.join().unwrap_or(());
507509
reader.join().unwrap_or(());
510+
511+
//wait untile this connection had been inserted connections map;
512+
sync_rx.recv().unwrap_or(());
513+
508514
// client_handler should not close fd before exit
509515
// , which prevent fd reuse issue.
510516
reaper_tx_child.send(pipe.id()).unwrap();
511517

512518
debug!("client thread quit");
513519
})
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));
527542
} // end loop
528543

529544
// notify reaper thread to exit.

0 commit comments

Comments
 (0)