From 66fc33399bf5f7d333e6900ef507db310a07ff24 Mon Sep 17 00:00:00 2001 From: SeongChan Lee Date: Tue, 15 Oct 2019 23:56:53 +0900 Subject: [PATCH] Fix race condition on `wait()` Manually dropping the future passed from `Future::select` before sending `done_tx` prevents the race condition. `Future::select` pass the unresolved future, which is a `Server` holding `rpc_handler`, to the following callback. Therefore, it is dropped after the `done_tx.send(())` after the callback exits. It is possible that the thread that has executed `wait()`, which is usually the main thread, terminates before the thread sending `done_tx` drops `rpc_handler`. Static variables are destructed at the end of termination of the main thread, and then a segfault occurs when the thread dropping the rpc_handler accesses the variables. --- http/src/lib.rs | 7 ++++++- ipc/src/server.rs | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/http/src/lib.rs b/http/src/lib.rs index caa599aa8..fc692f352 100644 --- a/http/src/lib.rs +++ b/http/src/lib.rs @@ -566,7 +566,12 @@ fn serve>( })) .map_err(|_| ()) }) - .and_then(|_| done_tx.send(())) + .and_then(|(_, server)| { + // We drop the server first to prevent a situation where main thread terminates + // before the server is properly dropped (see #504 for more details) + drop(server); + done_tx.send(()) + }) }); } diff --git a/ipc/src/server.rs b/ipc/src/server.rs index 8406afb86..933ad8648 100644 --- a/ipc/src/server.rs +++ b/ipc/src/server.rs @@ -240,7 +240,10 @@ impl> ServerBuilder { .buffer_unordered(1024) .for_each(|_| Ok(())) .select(stop) - .map(|_| { + .map(|(_, server)| { + // We drop the server first to prevent a situation where main thread terminates + // before the server is properly dropped (see #504 for more details) + drop(server); let _ = wait_signal.send(()); }) .map_err(|_| ()),