Summary: | Deadlock during IndexDiffCacheEntry$6.resourceChanged() call | ||
---|---|---|---|
Product: | [Technology] EGit | Reporter: | Andrey Loskutov <loskutov> |
Component: | Core | Assignee: | Andrey Loskutov <loskutov> |
Status: | RESOLVED FIXED | QA Contact: | |
Severity: | normal | ||
Priority: | P3 | CC: | matthias.sohn |
Version: | 4.0 | ||
Target Milestone: | 4.1 | ||
Hardware: | All | ||
OS: | All | ||
See Also: |
https://bugs.eclipse.org/bugs/show_bug.cgi?id=469566 https://bugs.eclipse.org/bugs/show_bug.cgi?id=382554 https://git.eclipse.org/r/49601 https://git.eclipse.org/c/egit/egit.git/commit/?id=f4e0e8bb5ba4fad5a672b3b403a12b94c624864a |
||
Whiteboard: |
Description
Andrey Loskutov
2015-06-07 02:56:35 EDT
Analysis: For whatever reason GitProjectData decided to logAndUnmapGoneMappedResource() on startup. I have no clue what this RepositoryMapping[<empty> -> '../../.git', absolute path: '/home/andrey/.git' ] could be because I do NOT have .git in my home, but this is another bug. So logAndUnmapGoneMappedResource() schedules UnmapJob for some project which simply calls RepositoryProvider.unmap(project). unmap() acquires first workspace rule for project, then mappingLock, and finally tries to call project.touch(null). This one requires another lock via workspace.prepareOperation() -> WorkManager.checkIn() -> lock.acquire() but this time the last lock is already taken by previously started workspace operation. This previously started operation (which we don't know what exact it did) is not finished yet, since it is dispatching resource change notification to listeners. One of this listeners is IndexDiffCacheEntry.resourceChangeListener which wants to know if a RepositoryMapping is known for the project in the resource delta. So it calls RepositoryMapping.getMapping(IProject) -> RepositoryProvider.getProvider(IProject, String) -> RepositoryProvider.mapExistingProvider() -> mappingLock.acquire() -> KABOOM. The case is almost identical to the bug 468270, so I've created bug 469566 to request non-locking RepositoryProvider.getProvider() team API. Of course we can't wait for the new team API and need support older Eclipse versions. So basically all uses of RepositoryProvider.getProvider(...) in egit code must be re-visited to check if they can deadlock. Most likely we want our own version of RepositoryProvider.getProvider implementation which never locks anything. Fix: https://git.eclipse.org/r/49601 The fix need to be tested. (In reply to Andrey Loskutov from comment #2) > Fix: https://git.eclipse.org/r/49601 > > The fix need to be tested. Not yet ready yet! Now without CVS/Subversion etc plugins there is no code anymore which would actually instantiate GitProvider - because it happened always indirectly as side effect of RepositoryProvider.getProvider() calls. OMG. So one MUST make sure that this code IS executed but please ONLY in specific threads and NOT in resource change listeners... This is extremely poor designed. Ideally I would expect that on workspace startup / projects initialization the configured team providers are initialized, but this seem to be not the case and we have lazy loading nightmare. |