Fix concurrency bug in PackageResolvers (#220)

Access to field "isClosed" must be guarded.
This commit is contained in:
translatenix
2024-02-20 16:46:09 -08:00
committed by GitHub
parent 277f1e0cdb
commit ffc629f28f

View File

@@ -36,6 +36,7 @@ import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
@@ -71,7 +72,7 @@ class PackageResolvers {
private final SecurityManager securityManager; private final SecurityManager securityManager;
private boolean isClosed = false; private final AtomicBoolean isClosed = new AtomicBoolean();
protected final Object lock = new Object(); protected final Object lock = new Object();
@@ -83,9 +84,7 @@ class PackageResolvers {
/** Retrieves a dependency's metadata file. */ /** Retrieves a dependency's metadata file. */
public DependencyMetadata getDependencyMetadata(PackageUri uri, @Nullable Checksums checksums) public DependencyMetadata getDependencyMetadata(PackageUri uri, @Nullable Checksums checksums)
throws IOException, SecurityManagerException { throws IOException, SecurityManagerException {
if (isClosed) { checkNotClosed();
throw new IllegalStateException();
}
synchronized (lock) { synchronized (lock) {
var metadata = cachedDependencyMetadata.get(uri); var metadata = cachedDependencyMetadata.get(uri);
if (metadata == null) { if (metadata == null) {
@@ -125,29 +124,23 @@ class PackageResolvers {
@Override @Override
public List<PathElement> listElements(PackageAssetUri uri, @Nullable Checksums checksums) public List<PathElement> listElements(PackageAssetUri uri, @Nullable Checksums checksums)
throws IOException, SecurityManagerException { throws IOException, SecurityManagerException {
if (isClosed) { checkNotClosed();
throw new IllegalStateException();
}
return doListElements(uri, checksums); return doListElements(uri, checksums);
} }
@Override @Override
public boolean hasElement(PackageAssetUri uri, @Nullable Checksums checksums) public boolean hasElement(PackageAssetUri uri, @Nullable Checksums checksums)
throws IOException, SecurityManagerException { throws IOException, SecurityManagerException {
if (isClosed) { checkNotClosed();
throw new IllegalStateException();
}
return doHasElement(uri, checksums); return doHasElement(uri, checksums);
} }
@Override @Override
public void close() throws IOException { public void close() throws IOException {
synchronized (lock) { if (!isClosed.getAndSet(true)) {
if (isClosed) { synchronized (lock) {
return; cachedDependencyMetadata.clear();
} }
cachedDependencyMetadata.clear();
isClosed = true;
} }
} }
@@ -236,6 +229,12 @@ class PackageResolvers {
packageUri.getDisplayName(), packageUri.getDisplayName(),
dependencyMetadata.getPackageZipUrl()); dependencyMetadata.getPackageZipUrl());
} }
private void checkNotClosed() {
if (isClosed.get()) {
throw new IllegalStateException("Package resolver has already been closed.");
}
}
} }
/** /**