-
Notifications
You must be signed in to change notification settings - Fork 15
Excavator: Upgrades Baseline to the latest version #5169
Conversation
012da33
to
4c08e41
Compare
7b38285
to
1859042
Compare
6dab4d8
to
b60ffa5
Compare
@@ -23,7 +23,9 @@ | |||
* determine that it is safe (or, at least, not obviously unsafe) to service requests. | |||
*/ | |||
@Value.Immutable | |||
@SuppressWarnings("ClassInitializationDeadlock") | |||
public interface TransactionManagerConsistencyResult { |
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.
The immutable is used outside of package
@@ -23,10 +23,11 @@ | |||
@JsonSerialize(as = ImmutableStreamStorePersistenceConfiguration.class) | |||
@JsonDeserialize(as = ImmutableStreamStorePersistenceConfiguration.class) | |||
@Value.Immutable | |||
@SuppressWarnings("ClassInitializationDeadlock") | |||
public interface StreamStorePersistenceConfiguration { |
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.
The immutable is used outside this package.
.failedUrlCooldown(Duration.ofMillis(1)) | ||
.maxNumRetries(5) | ||
.clientQoS(ClientConfiguration.ClientQoS.DANGEROUS_DISABLE_SYMPATHETIC_CLIENT_QOS) | ||
.build(); | ||
|
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.
This constant is only used for testing.
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 will assume that you verified this via a search on github? If so, great!
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 verified there are. no usages on internal github.
@@ -19,6 +19,8 @@ | |||
import org.immutables.value.Value; | |||
|
|||
@Value.Immutable | |||
@Value.Style(visibility = Value.Style.ImplementationVisibility.PACKAGE) | |||
@SuppressWarnings("ClassInitializationDeadlock") | |||
abstract class Token { | |||
@Nullable |
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.
Instead of breaking the interface contract by moving the constant, we are setting the impl visibility to PACKAGE (this is done to avoid initializing the immutable first) and suppressing the error.
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.
To clarify, is it the case that:
- setting the implementation visibility prevents the actual issue of initialisation deadlock?
- the check is not smart enough to determine this, and so it requires the warning to be suppressed?
- we cannot do this elsewhere because in other cases, the impl cannot be made package private? (In other words, why did we go with this solution here but not elsewhere, and vice versa?)
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.
setting the implementation visibility only helps avoid external usages which could potentially cause a deadlock and within the package we have to be sensible while using the immutable.
The check is still right in this case to break, which is why we suppress it.
This cannot be done in the cases where the subclass has usages in other packages. In those cases we move out the constants to a separate util. To have a separate a util only for a constant seems a but janky which is why we have take the first approach if possible.
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.
If we try to initialise ImmutableClass before Class, that will require us to initialise Class, but because of the static constant, that requires an initialisation of ImmutableClass and this deadlocks because there is a lock on ImmutableClass.
If you ensure that Class gets initialised first, then everything works fine, so by making access to ImmutableClass package private (to prevent external badness) and exposing a builder on the Class interface to be used instead of the ImmutableClass builder directly, we can avoid this issue
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.
Package private may still be accessed externally. I considered special casing in the errorprone rule, but it would require additional validation that nothing accesses package-private generated immutables outside of the defining class, which we've seen more frequently than one would hope.
@@ -23,6 +23,7 @@ | |||
import java.util.Set; | |||
import java.util.TreeMap; | |||
|
|||
@SuppressWarnings("ClassInitializationDeadlock") | |||
public abstract class KeyValueServiceInstrumentation { |
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.
The CassandraKeyValueServiceInstrumentation is being used in tests in a different package and can not be made package private, would appreciate alternative ideas for fixing the ClassInitDeadlock issue here.
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.
You can still make the generated code package private, and provide a builder in this class to avoid the issue outside of the package
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.
This is only used in benchmarking, and not worth the effort to clean it up
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.
🏁 00:10 | ⌛ 00:10
Thanks for doing this @sudiksha27. I think that there are two viable approaches for most of the fixes - deprecating and moving out those arbitrary constants (with a suppression of the warning in the mean time), and making package private and suppressing the warnings. However, I'm not too certain as to why we should use both approaches - are there times when one makes sense but not the other?
StreamStorePersistenceConfiguration DEFAULT_CONFIG = | ||
ImmutableStreamStorePersistenceConfiguration.builder().build(); | ||
|
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.
nit: unnecessary diff?
.failedUrlCooldown(Duration.ofMillis(1)) | ||
.maxNumRetries(5) | ||
.clientQoS(ClientConfiguration.ClientQoS.DANGEROUS_DISABLE_SYMPATHETIC_CLIENT_QOS) | ||
.build(); | ||
|
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 will assume that you verified this via a search on github? If so, great!
@@ -19,6 +19,8 @@ | |||
import org.immutables.value.Value; | |||
|
|||
@Value.Immutable | |||
@Value.Style(visibility = Value.Style.ImplementationVisibility.PACKAGE) | |||
@SuppressWarnings("ClassInitializationDeadlock") | |||
abstract class Token { | |||
@Nullable |
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.
To clarify, is it the case that:
- setting the implementation visibility prevents the actual issue of initialisation deadlock?
- the check is not smart enough to determine this, and so it requires the warning to be suppressed?
- we cannot do this elsewhere because in other cases, the impl cannot be made package private? (In other words, why did we go with this solution here but not elsewhere, and vice versa?)
public class PostgresKeyValueServiceInstrumentation extends KeyValueServiceInstrumentation { | ||
class PostgresKeyValueServiceInstrumentation extends KeyValueServiceInstrumentation { |
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.
Is this breaking?
@Value.Style(visibility = Value.Style.ImplementationVisibility.PACKAGE) | ||
@SuppressWarnings("ClassInitializationDeadlock") |
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.
nit: order is not consistent with the order of annotations on some of the other classes
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 make sure that you have the builders on the interfaces / abstract classes that have the constants and that the immutable builders are not used directly?
@@ -23,7 +23,9 @@ | |||
* determine that it is safe (or, at least, not obviously unsafe) to service requests. | |||
*/ | |||
@Value.Immutable | |||
@SuppressWarnings("ClassInitializationDeadlock") |
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.
@SuppressWarnings("ClassInitializationDeadlock") | |
@SuppressWarnings("ClassInitializationDeadlock") | |
@Value.Style(visibility = Value.Style.ImplementationVisibility.PACKAGE) |
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.
And add a builder if necessary for outside use, the idea is not to expose the generated immutable
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.
Curious why suppress an error-prone check for potential class initialization deadlock (see palantir/gradle-baseline#1598 that @carterkozak just added )? I'm assuming this is a fairly common pattern in many uses of immutables where there's either some constant defined as the empty object or similar. Do we need to consider pulling these types of constants out to a separate class (e.g. TransactionManagerConsistencyResults
) or lazy initialization get of a memoized supplier?
@@ -23,7 +23,9 @@ | |||
@JsonSerialize(as = ImmutableStreamStorePersistenceConfiguration.class) | |||
@JsonDeserialize(as = ImmutableStreamStorePersistenceConfiguration.class) | |||
@Value.Immutable | |||
@SuppressWarnings("ClassInitializationDeadlock") |
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.
@SuppressWarnings("ClassInitializationDeadlock") | |
@SuppressWarnings("ClassInitializationDeadlock") | |
@Value.Style(visibility = Value.Style.ImplementationVisibility.PACKAGE) |
@@ -19,6 +19,8 @@ | |||
import org.immutables.value.Value; | |||
|
|||
@Value.Immutable | |||
@Value.Style(visibility = Value.Style.ImplementationVisibility.PACKAGE) | |||
@SuppressWarnings("ClassInitializationDeadlock") | |||
abstract class Token { | |||
@Nullable |
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.
If we try to initialise ImmutableClass before Class, that will require us to initialise Class, but because of the static constant, that requires an initialisation of ImmutableClass and this deadlocks because there is a lock on ImmutableClass.
If you ensure that Class gets initialised first, then everything works fine, so by making access to ImmutableClass package private (to prevent external badness) and exposing a builder on the Class interface to be used instead of the ImmutableClass builder directly, we can avoid this issue
We came up with two options →
Given both changes can be breaking, we're inclined towards solution 1 as it will completely remove the code that is vulnerable to ClassInitDeadlock. |
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
Released 0.289.0 |
Looks like this may have raced another PR which added a potential deadlock |
excavator is a bot for automating changes across repositories.
Changes produced by the roomba/latest-baseline-oss check.
To enable or disable this check, please contact the maintainers of Excavator.