Skip to content
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

Merged
merged 1 commit into from
Oct 16, 2019
Merged

Fix race condition on wait() #504

merged 1 commit into from
Oct 16, 2019

Conversation

foriequal0
Copy link
Contributor

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.

I closed the previous PR (#501).
Sorry for the confusion.

@parity-cla-bot
Copy link

It looks like @foriequal0 signed our Contributor License Agreement. 👍

Many thanks,

Parity Technologies CLA Bot

Copy link
Contributor

@tomusdrw tomusdrw left a 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);
Copy link
Contributor

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)".

Copy link
Contributor

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?

@@ -240,7 +240,8 @@ impl<M: Metadata, S: Middleware<M>> ServerBuilder<M, S> {
.buffer_unordered(1024)
.for_each(|_| Ok(()))
.select(stop)
.map(|_| {
.map(|(_, other)| {
Copy link
Contributor

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.

@foriequal0
Copy link
Contributor Author

Thank you! I added comments to them.

@tomusdrw tomusdrw requested a review from dvdplm October 16, 2019 09:06
Copy link
Contributor

@dvdplm dvdplm left a 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);
Copy link
Contributor

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?

@tomusdrw
Copy link
Contributor

@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.
@tomusdrw tomusdrw merged commit d1993a8 into paritytech:master Oct 16, 2019
@foriequal0 foriequal0 deleted the fix/wait-race-2 branch October 16, 2019 10:37
foriequal0 added a commit to foriequal0/codechain that referenced this pull request Oct 18, 2019
The fix (paritytech/jsonrpc#504) has been merged
to `master`. It'll take times to relase, so use the merged master directly.
foriequal0 added a commit to foriequal0/codechain that referenced this pull request Oct 18, 2019
The fix (paritytech/jsonrpc#504) has been merged
to `master`. It'll take times to relase, so use the merged master directly.
foriequal0 added a commit to CodeChain-io/codechain that referenced this pull request Oct 18, 2019
The fix (paritytech/jsonrpc#504) has been merged
to `master`. It'll take times to relase, so use the merged master directly.
@niklasad1 niklasad1 mentioned this pull request Oct 18, 2019
foriequal0 added a commit to foriequal0/codechain that referenced this pull request Nov 8, 2019
The fix (paritytech/jsonrpc#504) has been merged
to `master`. It'll take times to relase, so use the merged master directly.
foriequal0 added a commit to CodeChain-io/codechain that referenced this pull request Nov 11, 2019
The fix (paritytech/jsonrpc#504) has been merged
to `master`. It'll take times to relase, so use the merged master directly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants