When MavenArtifactDownloader#_download is called with an artifact that is currently downloading, it waits on the other thread to complete the download. The problem is, that this is done inside the synchronized block.
This causes the waiting thread to hold the monitor of ACTIVE_DOWNLOADS indefinitely and blocks every other request for MavenArtifactDownloader. The problem arises if the artifact that currently is being downloaded is a generated artifact that relies on MavenArtifactDownloader to generate.
When does the issue occur in practise?
If a project has fg.deobf(...) dependencies, they'll be resolved together with the minecraft dependency. This causes both Deobfuscator#findMapping and MinecraftUserRepo#findMapping to be called in parallel, where both of them download the same mappings artifact through MavenArtifactDownloader.
The first call to MavenArtifactDownloader.download will start a mapping lookup through MCPRepo which calls the matching channel provider. The second call to MavenArtifactDownloader.download then waits for the download to complete which completely locks MavenArtifactDownloader for any artifact.
If the channel provider then uses MavenArtifactDownloader in its getMappingsFile method (which both builtin channel providers do), this can cause a deadlock.
As MavenArtifactDownloader#download calls happen very early in the builtin channel providers, it is unlikely, yet still possible for a deadlock to occur. Other 3rd party channel providers however, might call MavenArtifactDownloader#download later and do other stuff before, so they can become more prone for deadlocks.
When
MavenArtifactDownloader#_download
is called with an artifact that is currently downloading, it waits on the other thread to complete the download. The problem is, that this is done inside thesynchronized
block.This causes the waiting thread to hold the monitor of
ACTIVE_DOWNLOADS
indefinitely and blocks every other request forMavenArtifactDownloader
. The problem arises if the artifact that currently is being downloaded is a generated artifact that relies onMavenArtifactDownloader
to generate.When does the issue occur in practise?
If a project has
fg.deobf(...)
dependencies, they'll be resolved together with theminecraft
dependency. This causes both Deobfuscator#findMapping and MinecraftUserRepo#findMapping to be called in parallel, where both of them download the same mappings artifact throughMavenArtifactDownloader
.The first call to
MavenArtifactDownloader.download
will start a mapping lookup through MCPRepo which calls the matching channel provider. The second call toMavenArtifactDownloader.download
then waits for the download to complete which completely locksMavenArtifactDownloader
for any artifact.If the channel provider then uses
MavenArtifactDownloader
in its getMappingsFile method (which both builtin channel providers do), this can cause a deadlock.As
MavenArtifactDownloader#download
calls happen very early in the builtin channel providers, it is unlikely, yet still possible for a deadlock to occur. Other 3rd party channel providers however, might callMavenArtifactDownloader#download
later and do other stuff before, so they can become more prone for deadlocks.