-
Notifications
You must be signed in to change notification settings - Fork 272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix race condition on wait()
#504
Conversation
It looks like @foriequal0 signed our Contributor License Agreement. 👍 Many thanks, Parity Technologies CLA Bot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thank you! The code looks a bit mystical at first sight, so I think it would be good to add a short comment explaining what we do and pointing to this PR.
http/src/lib.rs
Outdated
@@ -565,7 +565,10 @@ fn serve<M: jsonrpc::Metadata, S: jsonrpc::Middleware<M>>( | |||
})) | |||
.map_err(|_| ()) | |||
}) | |||
.and_then(|_| done_tx.send(())) | |||
.and_then(|(_, other)| { | |||
drop(other); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment what are we dropping here and why? Something like:
"We drop the Server
first to prevent a situation where main thread terminates before the Server
is properly dropped (see #504 for more details)".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe s/other/server/ then?
ipc/src/server.rs
Outdated
@@ -240,7 +240,8 @@ impl<M: Metadata, S: Middleware<M>> ServerBuilder<M, S> { | |||
.buffer_unordered(1024) | |||
.for_each(|_| Ok(())) | |||
.select(stop) | |||
.map(|_| { | |||
.map(|(_, other)| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here if you don't mind.
Thank you! I added comments to them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, modulo the variable naming, "other" is a bit obscure.
http/src/lib.rs
Outdated
@@ -565,7 +565,10 @@ fn serve<M: jsonrpc::Metadata, S: jsonrpc::Middleware<M>>( | |||
})) | |||
.map_err(|_| ()) | |||
}) | |||
.and_then(|_| done_tx.send(())) | |||
.and_then(|(_, other)| { | |||
drop(other); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe s/other/server/ then?
@foriequal0 please rebase as well while you address @dvdplm's grumble. |
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.
The fix (paritytech/jsonrpc#504) has been merged to `master`. It'll take times to relase, so use the merged master directly.
The fix (paritytech/jsonrpc#504) has been merged to `master`. It'll take times to relase, so use the merged master directly.
The fix (paritytech/jsonrpc#504) has been merged to `master`. It'll take times to relase, so use the merged master directly.
The fix (paritytech/jsonrpc#504) has been merged to `master`. It'll take times to relase, so use the merged master directly.
The fix (paritytech/jsonrpc#504) has been merged to `master`. It'll take times to relase, so use the merged master directly.
Manually dropping the future passed from
Future::select
before sendingdone_tx
prevents the race condition.Future::select
pass the unresolved future, which is aServer
holdingrpc_handler
, to the following callback. Therefore, it is dropped afterthe
done_tx.send(())
after the callback exits.It is possible that the thread that has executed
wait()
, which isusually 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.
I closed the previous PR (#501).
Sorry for the confusion.