facebook / facebook/infer

Very frequent false negatives in RacerD

Open
#2,020 0 comments 0 reactions 0 assignees View on GitHub
false-negative java
Dominant language
OCaml
Stars
15.7k
Forks
2.1k
Avg merge
19h 36m
Merged PRs (30d)
13

Description

I write test cases to evaluate RacerD concurrency issues detection rate. I have created several tests, but majority of them are false negative.

Examples:

Example 1 (if I would replace HashSet with HashMap, then RacerD can detect issues, but for HashSet no chance; I tried to add @ThreadSafe, tried to call from another class which starts two threads and calls addData/getData etc. None of the combinations detect the race.

```
public class UnsafeSetWithSynchronized1_FALSE_NEGATIVE {
private final Set data = new HashSet<>();

public synchronized void addData(String value) {
data.add(value);
}

public boolean contains(String value) {
return data.contains(value);
}

public Set getData() {
return data;
}
}

```
Example 2:

```
public class UnsafeObjectConditionWithSynchronized1_FALSE_NEGATIVE {
private boolean flag;

public void set(boolean flag) {
this.flag = flag;
}

public synchronized int get() {
if (flag) {
return 0;
} else {
return 1;
}
}
}

```
Example 3:

```
public class UnsafeListInParallelStreamWithSynchronized_FALSE_NEGATIVE {
private final List data = new ArrayList<>();

public synchronized void processData(List ids) {
// multiple threads will try to add to the list simultaneously
ids.parallelStream().forEach(id -> {
data.add(id);
});
}

public List get() {
return data;
}
}
```

Example 4:

```
@ThreadSafe
public class UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE {
private final Set data = new HashSet<>();

public synchronized void addData(String value) {
data.add(value);
}

public boolean contains(String value) {
return data.contains(value);
}

public Set getData() {
return data;
}

public static UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE createAndStartNew() {
UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE instance = new UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE();

Thread t = new Thread(() -> {
instance.addData("Auto-generated data");
});
t.start();

return instance;
}

public static Thread useAndStartExisting1(UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE existing) {
Thread t = new Thread(() -> {
existing.contains("Some value");
});

return t;
}

public static Thread useAndStartExisting2(UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE existing) {
Thread t = new Thread(() -> {
existing.addData("Some value");
});

return t;
}

public static Set useAndStartExisting3(UnsafeSetWithThreadsSynchronizedAndThreadSafeAnnotation_FALSE_NEGATIVE existing) throws InterruptedException {
Set result = new HashSet<>();
Thread t = new Thread(() -> {
result.addAll(existing.getData());
});

t.start();
t.join();

return result;
}

}

```
And lots of other examples ... only in limited number of cases RacerD could discover some data race.

I start RacerD in following way:

```
ProcessBuilder pb = new ProcessBuilder(
INFER_PATH, "run",
"--racerd-only",
"--reactive",
"--no-filtering", // Disables noise filters
"--", "/usr/bin/javac", "-cp", ANNOTATIONS_JAR_PATH, filePath.toString()
);
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.