-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
HBASE-28010: Prevent connection attribute corruption #5366
Conversation
f1452d9
to
60885cc
Compare
💔 -1 overall
This message was automatically generated. |
60885cc
to
a99d6b9
Compare
hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/ServerRpcConnection.java
Outdated
Show resolved
Hide resolved
...-server/src/test/java/org/apache/hadoop/hbase/client/TestRequestAndConnectionAttributes.java
Outdated
Show resolved
Hide resolved
...-server/src/test/java/org/apache/hadoop/hbase/client/TestRequestAndConnectionAttributes.java
Outdated
Show resolved
Hide resolved
💔 -1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
if (header.getAttributeList().isEmpty()) { | ||
this.requestAttributes = Collections.emptyMap(); | ||
} else { | ||
this.requestAttributes = Maps.newHashMapWithExpectedSize(header.getAttributeList().size()); |
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.
I don't think we need to synchronize this method given the chances of threading issues (low) and the cost of the computation (low), but we should consider thread safety here nonetheless.
At the very least, we should make this.requestAttributes
volatile. Then here we should construct a local map and add the values onto it, then only do this.requestAttributes = localAttributes
at the end. This way if there did happen to be 2 callers, one would not get an incomplete view of the request attributes.
@@ -405,6 +410,16 @@ private CodedInputStream createCis(ByteBuff buf) { | |||
// Reads the connection header following version | |||
private void processConnectionHeader(ByteBuff buf) throws IOException { | |||
this.connectionHeader = ConnectionHeader.parseFrom(createCis(buf)); | |||
if (connectionHeader.getAttributeList().isEmpty()) { |
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.
can you add a comment here that we want to copy the attributes prior to releasing the buffer so that they don't get corrupted down the line when the buffer's underlying memory is replaced for some other call?
@@ -83,7 +86,17 @@ public interface RpcCall extends RpcCallContext { | |||
/** Returns The request header of this call. */ | |||
RequestHeader getHeader(); | |||
|
|||
ConnectionHeader getConnectionHeader(); | |||
/** | |||
* Returns the map of attributes specified when building the Connection See the Map argument on |
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.
nitpick: since you already have to do one more revision can you fix this and below javadoc to at least add a period prior to See the..
? Could also add a <br>
if you want them to be on the next line, or better yet use @see
, i.e.:
/**
* Returns the map of attributes specified when building the Connection.
* @see ConnectionFactory#createConnection(Configuration, ExecutorService, User, Map)
*/
The see will automatically also do the linking.
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 thanks! I'll merge once all of the pre-commit checks come back green.
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
@rmdmattingly Looks like the Maps imports are wrong, so the build is failing. |
Yep I’ve pushed a fix already |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
Looking better but now there are some unused imports in RpcCall, per checkstyle |
🤦I can never keep track of what spotless cleans up and what it leaves behind. Fixing now |
Ah ok, it's these imports that are only servicing the javadoc — I can remove those to appease checkstyle, but IMO it makes the javadoc marginally worse. Is that fine? |
Interesting. I feel like it's a bug due to the splitting of the |
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
Test failures don't seem relevant:
|
…side (#5366) Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
…side (#5366) Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
…ted on the server side (apache#5366) Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
…side (apache#5366) Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
In ServerRpcConnection.processOneRpc, it calls processConnectionHeader and then immediately calls callCleanupIfNeeded. The parsing of the ByteBuff into the ConnectionHeader does not copy the bytes. We keep a reference to ConnectionHeader for later use, but since the underlying ByteBuff gets released in callCleanupIfNeeded, later requests can override the memory locations that the ConnectionHeader points at.
In this PR we modified our test to ensure that it failed in the current state on master — enabling the byte buffer resevoir and sending a large enough put caused the ConnectionHeader attributes to disappear. We fixed this by copying the parsed ConnectionHeader's attributes to their own Map, and then making this Map accessible on the RpcCall.
@bbeaudreault