You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.2 KiB

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package codetoanalyze.java.checkers;
import com.facebook.infer.annotation.ThreadSafe;
import com.google.common.annotations.VisibleForTesting;
class ThreadSafeMethods {
Object field1;
Object field2;
Object field3;
Object field4;
Object field5;
@ThreadSafe
public void threadSafeMethodWriteBad() {
this.field1 = new Object(); // should warn
}
@ThreadSafe
public Object threadSafeMethodReadBad() {
return this.field2;
}
@ThreadSafe
private void threadSafePrivateMethodBad() {
this.field2 = new Object(); // should warn
}
@ThreadSafe
@VisibleForTesting
public void threadSafeVisibleForTestingMethodBad() {
this.field3 = new Object(); // should warn
}
@ThreadSafe
public void safeMethodOverride() {}
// if a method annotated with @ThreadSafe in class C writes field f, then all other accesses to f
// in C must also be thread-safe
public void writeSameFieldAsThreadSafeMethod1Bad() {
// warn here because field1 is also written in @ThreadSafe method threadSafeMethodWriteBad
this.field1 = new Object();
}
// reads a field that is written in a method marked thread-safe
public Object readSameFieldAsThreadSafeMethod1Bad() {
return this.field1;
}
// TODO: should we report this or not?
public synchronized void safelyWriteSameFieldAsThreadSafeMethod1Ok() {
this.field1 = new Object();
}
public synchronized Object readSameFieldAsThreadSafeMethodWhileSynchronized1Bad() {
return this.field1;
}
@ThreadSafe
public synchronized void synchronizedWriteOk() {
this.field4 = new Object();
}
// unprotected write to a field that is written safely in a method marked thread-safe
public void writeSameFieldAsThreadSafeMethod2Bad() {
this.field4 = new Object();
}
// unprotected read of a field that is written safely in a method marked thread-safe
public Object readSameFieldAsThreadSafeMethod2Bad() {
return this.field4;
}
@ThreadSafe
public synchronized Object FN_synchronizedReadBad() {
return this.field5;
}
private void privateAccessOk() {
this.field5 = new Object();
}
// unprotected write to a field that is read safely in a method marked thread-safe
public void FN_writeSameFieldAsThreadSafeMethod3Bad() {
this.field5 = new Object();
}
[thread-safety] Change meaning of @ThreadSafe to "can run in parallel with any thread including itself" Summary: Previously, annotating something ThreadSafe meant "check that it is safe to run all of this procedure's methods in parallel with each other" (including self-parallelization). This makes sense, but it means that if the user writes no annotations, we do no checking. I'm moving toward a model of inferring when an access might happen on a thread that can run concurrently with other threads, then automatically checking that it is thread-safe w.r.t to all other accesses to the same memory (on or off the current thread thread). This will let us report even when there are no `ThreadSafe` annotations. Any method that is known to run on a new thread (e.g., `Runnable.run`) will be modeled as running on a thread that can run in parallel with other threads, and so will any method that is `synchronized` or acquires a lock. In this setup, adding `ThreadSafe` to a method just means: "assume that the current method can run in parallel with any thread, including another thread that includes a different invocation of the same method (a self race) unless you see evidence to the contrary" (e.g., calling `assertMainThread` or annotating with `UiThread`). The key step in this diff is changing the threads domain to abstract *what threads the current thread may run in parallel with* rather than *what the current thread* is. This makes things much simpler. Reviewed By: jberdine Differential Revision: D5895242 fbshipit-source-id: 2e23d1e
7 years ago
// none of the writes are marked thread-safe/locked, no reason to report
public Object readSameFieldAsThreadSafeMethodOk() {
return this.field5;
}
}
class ThreadSafeMethodsSubclass extends ThreadSafeMethods {
Object subclassField;
@Override
// overrides method annotated with @ThreadSafe, should warn
public void safeMethodOverride() {
this.subclassField = new Object();
}
public void FN_writeThreadSafeFieldOfSuperclassBad() {
this.field1 = new Object();
}
public Object FN_readThreadSafeFieldOfSuperclassBad() {
return this.field1;
}
public void writeThreadSafeFieldOfOverrideBad() {
this.subclassField = new Object();
}
public Object readThreadSafeFieldOfOverrideBad() {
return this.subclassField;
}
}