|
|
|
This warning indicates a potential data race in Java. The analyser is called
|
|
|
|
RacerD and this section gives brief but a mostly complete description of its
|
|
|
|
features. See the [RacerD page](/docs/next/checker-racerd) for more in-depth information and
|
|
|
|
examples.
|
|
|
|
|
|
|
|
### Thread-safety: What is a data race
|
|
|
|
|
|
|
|
Here a data race is a pair of accesses to the same member field such that:
|
|
|
|
|
|
|
|
- at least one is a write, and,
|
|
|
|
- at least one occurs without any lock synchronization, and,
|
|
|
|
- the two accesses occur on threads (if known) which can run in parallel.
|
|
|
|
|
|
|
|
### Thread-safety: Potential fixes
|
|
|
|
|
|
|
|
- Synchronizing the accesses (using the `synchronized` keyword, thread-exclusion
|
|
|
|
such as atomic objects, `volatile` etc).
|
|
|
|
- Making an offending method private -- this will exclude it from being checked
|
|
|
|
at the top level, though it will be checked if called by a public method which
|
|
|
|
may itself, e.g., hold a lock when calling it.
|
|
|
|
- Putting the two accesses on the same thread, e.g., by using `@MainThread` or
|
|
|
|
`@ThreadConfined`.
|
|
|
|
|
|
|
|
### Thread-safety: Conditions checked before reporting
|
|
|
|
|
|
|
|
The class and method are not marked `@ThreadSafe(enableChecks = false)`, and,
|
|
|
|
|
|
|
|
- The method is declared `synchronized`, or employs (non-transitively) locking,
|
|
|
|
or,
|
|
|
|
- The class is not marked `@NotThreadSafe`, and,
|
|
|
|
- The class/method is marked `@ThreadSafe,` or one of the configured synonyms
|
|
|
|
in `.inferconfig`, or,
|
|
|
|
- A parent class, or an override method are marked with the above annotations.
|
|
|
|
|
|
|
|
NB currently RacerD **does not take into account `@GuardedBy`**.
|
|
|
|
|
|
|
|
### Thread-safety: Thread annotations recognized by RacerD
|
|
|
|
|
|
|
|
These class and method annotations imply the method is on the main thread:
|
|
|
|
`@MainThread`, `@UiThread`
|
|
|
|
|
|
|
|
These method annotations imply the method is on the main thread: `@OnBind`,
|
|
|
|
`@OnEvent`, `@OnMount`, `@OnUnbind`, `@OnUnmount`
|
|
|
|
|
|
|
|
Both classes of annotations work through the inheritance tree (i.e. if a parent
|
|
|
|
class or method is marked with one of these annotations, so is the child class /
|
|
|
|
method override).
|
|
|
|
|
|
|
|
In addition to these, RacerD recognizes many lifecycle methods as necessarily
|
|
|
|
running on the main thread, eg `Fragment.onCreate` etc.
|
|
|
|
|
|
|
|
Finally, the thread status of being on the main thread propagates backwards
|
|
|
|
through the call graph (ie if `foo` calls `bar` and `bar` is marked `@UiThtread`
|
|
|
|
then `foo` is automatically considered on the main thread too). Calling
|
|
|
|
`assertMainThread`, `assertOnUiThread`, `checkOnMainThread` has the same effect.
|
|
|
|
|
|
|
|
NB RacerD currently **does not recognize `@WorkerThread`, `@BinderThread` or
|
|
|
|
`@AnyThread`**.
|
|
|
|
|
|
|
|
### Thread-safety: Other annotations and what they do
|
|
|
|
|
|
|
|
These annotations can be found at `com.facebook.infer.annotation.*`.
|
|
|
|
|
|
|
|
- `@Functional` This is a method annotation indicating the method always returns
|
|
|
|
the same value. When a method `foo` is annotated `@Functional`, RacerD will
|
|
|
|
ignore any writes of the return value of `foo`. For example, in
|
|
|
|
`this.x = foo()`, the write to `this.x` is ignored. The reasoning is that if
|
|
|
|
the method returns the same value whenever it's called, any data race on
|
|
|
|
`this.x` is benign, if that is the only write.
|
|
|
|
|
|
|
|
- `@ThreadConfined` This is a class/method/field annotation which takes a single
|
|
|
|
parameter which can be `UI`, `ANY` or a user chosen string. It indicates to
|
|
|
|
RacerD a thread identifier for the class/method/field. Thus,
|
|
|
|
`@ThreadConfined(UI)` is equivalent to `@UiThread`, and `@ThreadConfined(ANY)`
|
|
|
|
is equivalent to not having the annotation at all, for classes and methods.
|
|
|
|
When this annotation is applied to a field it instructs Infer to assume
|
|
|
|
(without checking) that all accesses to that field are made on the same thread
|
|
|
|
(and can, therefore, not race by definition). The intention is that RacerD
|
|
|
|
uses that to detect exclusion between accesses occurring on the same thread.
|
|
|
|
However, only the UI thread is supported at this time, and any user provided
|
|
|
|
value is considered equal to `UI`.
|
|
|
|
|
|
|
|
- `@VisibleForTesting` A method annotation making Infer consider the method as
|
|
|
|
effectively `private`. This means it will not be checked for races against
|
|
|
|
other non-private methods of the class, but only if called by one.
|
|
|
|
|
|
|
|
- `@ReturnsOwnership` A method annotation indicating that the method returns a
|
|
|
|
freshly owned object. Accesses to the returned value will not be considered
|
|
|
|
for data races, as the object is in-effect unique and not accessible yet from
|
|
|
|
other threads. The main utility of this annotation is in interfaces, where
|
|
|
|
Infer cannot look up the implementation and decide for itself.
|