Skip to content

Commit 2244900

Browse files
authored
Merge pull request #300 from lifupan/fix_fd_leak
sync: fix the connection fd leak on the server side
2 parents 4929e90 + 370459c commit 2244900

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)