Skip to content

I20190626-1800

@trancexpress trancexpress tagged this 26 Jun 09:11
Concurrent calls to BinaryType.exists() can sometimes result in false
for one of the callers, despite the type existing.

This is the case due to the two-cache approach in JavaModelManager - it
has thread local JavaModelManager.temporaryCache and global shared
JavaModelManager.cache.

Given two threads calling BinaryType.exists() and nothing is in the
global cache, the 1st thread adds the necessary types to the shared
JavaModelManager.cache via JavaElement.openWhenClosed(), while the 2nd
thread enters JavaElement.openWhenClosed() and is at the beginning of
SourceRefElement.generateInfos().

In the SourceRefElement.generateInfos() 2nd thread then finds element
info for the parent of the BinaryType and assumes there is nothing to be
done, so it leaves the local JavaModelManager.temporaryCache empty.

After the call of SourceRefElement.generateInfos()
JavaElement.openWhenClosed() can't find anything in the local cache and
throws a JavaModelException which causes BinaryType.exists() to return
"false", which is wrong and not expected by the caller.

With this change, JavaElement.openWhenClosed() takes this case into
account and double checks with the JavaModelManager if no info was
generated during JavaElement.generateInfos(). This ensures that no
exception is thrown and that the correct element info is returned by
JavaElement.openWhenClosed(). Without the exception, BinaryType.exists()
returns true as expected.

This change also adds a test which can sometimes show the behavior with
sufficient repetition, if no fix is applied.

To observe the problem manually:

1. set repetition in the test to 1
2. set a breakpoint at the start of: SourceRefElement.generateInfos()
3. run the test
4. resume one of the threads at the breakpoint from 2.
5. resume the other thread at the breakpoint from 2.
6. observe that BinaryType.exists() returns false for the 2nd thread

Change-Id: Id576dd5eabfa060277ab31a9c7eb8da05ce71410
Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
Assets 2
Loading