-
Notifications
You must be signed in to change notification settings - Fork 3.9k
CallOptions is not thread-safe #9658
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
Comments
You are sharing the object with unsynchronized publication. I don't think we care at all about unsynchronized publication, as it is generally seen as an antipattern and so mostly matters for security-related objects. But I do see that
Since this object is created enough that we don't want to use a separate internal builder just to improve the ease of setting final fields, I think we'd just remove the annotation and use text to say the object is immutable but may not be published without synchronization. |
Right, that was my point.
Couldn't the internal code just "grin and bear it" with a high-arity constructor? It's not as though it's exposed as part of the API. For code that changes infrequently it doesn't seem THAT error prone (e.g. with comments), or is it a matter of it simply be banned by some style guide / convention? It seems to me the fields being final outweighs the ugliness of a high-arity constructor. |
Yeah, the code could just grin and bear it. It is easy to mix up argument ordering and the like, though. And adding a new field becomes annoying. There is also a potential option of trying out a builder and seeing if C2 JIT actually avoids the builder allocation.
What is the benefit? I don't think normal usages in gRPC would see any benefit, even for |
Looks like on OpenJDK the Builder allocation is properly optimized away. That'd probably be true on Android as well, as the code is pretty canonical for "temporary stack object." So I'm fine swapping to an internal builder. |
I guess the main benefit would be not having to explain in the Javadoc that the class is immutable but not thread-safe, which seems awkward 😄
Great, sounds good. |
Although CallOptions is annotated by @immutable, its fields are not final. So it's not truly immutable, namely not safe for unsynchronized publication. This commit adds final to all fields of CallOptions. Using internal builder class to keep flexibility of constructing CallOptions. Fixes #9658
Although it is annotated with
Immutable
, CallOptions has no final fields, and is therefore not actually thread-safe. The javadoc for theImmutable
annotations states:This can be shown to be violated with a simple JCStress test case; here is an example.
When I run the above test case on my aarch64 machine, I get results such as the following, showing memory visibility issues:
Although to be honest, the above test case is not really needed, as one can simply refer to the JLS [1] [2] to see that CallOptions is not safely published and is therefore not guaranteed to be seen as consistent across threads.
The CallOptions class has a comment explaining why the fields are not final, and it seems to be for stylistic reasons. I would think correctness would outweigh such concerns and the fields should be made final, or the
Immutable
annotation should be removed from the class.[1] https://shipilev.net/blog/2014/safe-public-construction/#_safe_publication
[2] https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5
The text was updated successfully, but these errors were encountered: