Skip to content

Commit

Permalink
8325179: Race in BasicDirectoryModel.validateFileCache
Browse files Browse the repository at this point in the history
8238169: BasicDirectoryModel getDirectories and DoChangeContents.run can deadlock

Reviewed-by: prr, tr, aturbanov, serb
  • Loading branch information
aivanov-jdk committed Mar 21, 2024
1 parent 1496b5d commit e66788c
Showing 1 changed file with 48 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,13 @@ public void propertyChange(PropertyChangeEvent e) {
* This method is used to interrupt file loading thread.
*/
public void invalidateFileCache() {
if (filesLoader != null) {
filesLoader.loadThread.interrupt();
filesLoader.cancelRunnables();
filesLoader = null;
synchronized (this) {
if (filesLoader != null) {
filesLoader.loadThread.interrupt();
filesLoader = null;
// Increment fetch ID to invalidate pending DoChangeContents
fetchID.incrementAndGet();
}
}
}

Expand Down Expand Up @@ -156,14 +159,15 @@ public void validateFileCache() {
if (currentDirectory == null) {
return;
}
if (filesLoader != null) {
filesLoader.loadThread.interrupt();
filesLoader.cancelRunnables();
}
synchronized (this) {
if (filesLoader != null) {
filesLoader.loadThread.interrupt();
}

int fid = fetchID.incrementAndGet();
setBusy(true, fid);
filesLoader = new FilesLoader(currentDirectory, fid);
int fid = fetchID.incrementAndGet();
setBusy(true, fid);
filesLoader = new FilesLoader(currentDirectory, fid);
}
}

/**
Expand Down Expand Up @@ -276,7 +280,6 @@ private final class FilesLoader implements Runnable {
private final boolean fileSelectionEnabled;
private final int fid;
private final File currentDirectory;
private volatile DoChangeContents runnable;
private final Thread loadThread;

private FilesLoader(File currentDirectory, int fid) {
Expand All @@ -297,22 +300,20 @@ public void run() {
}

private void run0() {
FileSystemView fileSystem = fileSystemView;

if (loadThread.isInterrupted()) {
return;
}

File[] list = fileSystem.getFiles(currentDirectory, useFileHiding);
File[] list = fileSystemView.getFiles(currentDirectory, useFileHiding);

if (loadThread.isInterrupted()) {
return;
}

final Vector<File> newFileCache = new Vector<File>();
Vector<File> newFiles = new Vector<File>();
final Vector<File> newFiles = new Vector<File>();

// run through the file list, add directories and selectable files to fileCache
// Run through the file list, add directories and selectable files to fileCache
// Note that this block must be OUTSIDE of Invoker thread because of
// deadlock possibility with custom synchronized FileSystemView
for (File file : list) {
Expand All @@ -339,7 +340,7 @@ private void run0() {

// To avoid loads of synchronizations with Invoker and improve performance we
// execute the whole block on the COM thread
runnable = ShellFolder.invoke(new Callable<DoChangeContents>() {
DoChangeContents runnable = ShellFolder.invoke(new Callable<DoChangeContents>() {
public DoChangeContents call() {
synchronized (fileCache) {
int newSize = newFileCache.size();
Expand Down Expand Up @@ -395,7 +396,7 @@ public DoChangeContents call() {
}
if (!fileCache.equals(newFileCache)) {
if (loadThread.isInterrupted()) {
cancelRunnables();
return null;
}
return new DoChangeContents(newFileCache, 0, fileCache, 0, fid);
}
Expand All @@ -408,12 +409,6 @@ public DoChangeContents call() {
SwingUtilities.invokeLater(runnable);
}
}

private void cancelRunnables() {
if (runnable != null) {
runnable.cancel();
}
}
}


Expand Down Expand Up @@ -522,45 +517,46 @@ public void run() {
private final class DoChangeContents implements Runnable {
private final List<File> addFiles;
private final List<File> remFiles;
private boolean doFire = true;
private final int fid;
private int addStart = 0;
private int remStart = 0;
private final int addStart;
private final int remStart;

DoChangeContents(List<File> addFiles, int addStart, List<File> remFiles,
int remStart, int fid) {
private DoChangeContents(List<File> addFiles, int addStart,
List<File> remFiles, int remStart,
int fid) {
this.addFiles = addFiles;
this.addStart = addStart;
this.remFiles = remFiles;
this.remStart = remStart;
this.fid = fid;
}

synchronized void cancel() {
doFire = false;
}
@Override
public void run() {
if (fetchID.get() != fid) {
return;
}

public synchronized void run() {
if (fetchID.get() == fid && doFire) {
int remSize = (remFiles == null) ? 0 : remFiles.size();
int addSize = (addFiles == null) ? 0 : addFiles.size();
synchronized(fileCache) {
if (remSize > 0) {
fileCache.removeAll(remFiles);
}
if (addSize > 0) {
fileCache.addAll(addStart, addFiles);
}
files = null;
directories = null;
final int remSize = (remFiles == null) ? 0 : remFiles.size();
final int addSize = (addFiles == null) ? 0 : addFiles.size();
final int cacheSize;
synchronized (fileCache) {
if (remSize > 0) {
fileCache.removeAll(remFiles);
}
if (remSize > 0 && addSize == 0) {
fireIntervalRemoved(BasicDirectoryModel.this, remStart, remStart + remSize - 1);
} else if (addSize > 0 && remSize == 0 && addStart + addSize <= fileCache.size()) {
fireIntervalAdded(BasicDirectoryModel.this, addStart, addStart + addSize - 1);
} else {
fireContentsChanged();
if (addSize > 0) {
fileCache.addAll(addStart, addFiles);
}
files = null;
directories = null;
cacheSize = fileCache.size();
}
if (remSize > 0 && addSize == 0) {
fireIntervalRemoved(BasicDirectoryModel.this, remStart, remStart + remSize - 1);
} else if (addSize > 0 && remSize == 0 && addStart + addSize <= cacheSize) {
fireIntervalAdded(BasicDirectoryModel.this, addStart, addStart + addSize - 1);
} else {
fireContentsChanged();
}
}
}
Expand Down

9 comments on commit e66788c

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aivanov-jdk
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/backport jdk22u

@openjdk
Copy link

@openjdk openjdk bot commented on e66788c Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aivanov-jdk the backport was successfully created on the branch backport-aivanov-jdk-e66788c1 in my personal fork of openjdk/jdk22u. To create a pull request with this backport targeting openjdk/jdk22u:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit e66788c1 from the openjdk/jdk repository.

The commit being backported was authored by Alexey Ivanov on 21 Mar 2024 and was reviewed by Phil Race, Tejesh R, Andrey Turbanov and Sergey Bylokhov.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk22u:

$ git fetch https://github.com/openjdk-bots/jdk22u.git backport-aivanov-jdk-e66788c1:backport-aivanov-jdk-e66788c1
$ git checkout backport-aivanov-jdk-e66788c1
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk22u.git backport-aivanov-jdk-e66788c1

@TheRealMDoerr
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/backport jdk21u-dev

@openjdk
Copy link

@openjdk openjdk bot commented on e66788c May 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TheRealMDoerr the backport was successfully created on the branch backport-TheRealMDoerr-e66788c1 in my personal fork of openjdk/jdk21u-dev. To create a pull request with this backport targeting openjdk/jdk21u-dev:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit e66788c1 from the openjdk/jdk repository.

The commit being backported was authored by Alexey Ivanov on 21 Mar 2024 and was reviewed by Phil Race, Tejesh R, Andrey Turbanov and Sergey Bylokhov.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk21u-dev:

$ git fetch https://github.com/openjdk-bots/jdk21u-dev.git backport-TheRealMDoerr-e66788c1:backport-TheRealMDoerr-e66788c1
$ git checkout backport-TheRealMDoerr-e66788c1
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk21u-dev.git backport-TheRealMDoerr-e66788c1

@TheRealMDoerr
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/backport jdk17u-dev

@openjdk
Copy link

@openjdk openjdk bot commented on e66788c Jun 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TheRealMDoerr the backport was successfully created on the branch backport-TheRealMDoerr-e66788c1-master in my personal fork of openjdk/jdk17u-dev. To create a pull request with this backport targeting openjdk/jdk17u-dev:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit e66788c1 from the openjdk/jdk repository.

The commit being backported was authored by Alexey Ivanov on 21 Mar 2024 and was reviewed by Phil Race, Tejesh R, Andrey Turbanov and Sergey Bylokhov.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk17u-dev:

$ git fetch https://github.com/openjdk-bots/jdk17u-dev.git backport-TheRealMDoerr-e66788c1-master:backport-TheRealMDoerr-e66788c1-master
$ git checkout backport-TheRealMDoerr-e66788c1-master
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk17u-dev.git backport-TheRealMDoerr-e66788c1-master

@TheRealMDoerr
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/backport jdk11u-dev

@openjdk
Copy link

@openjdk openjdk bot commented on e66788c Jun 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TheRealMDoerr the backport was successfully created on the branch backport-TheRealMDoerr-e66788c1-master in my personal fork of openjdk/jdk11u-dev. To create a pull request with this backport targeting openjdk/jdk11u-dev:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit e66788c1 from the openjdk/jdk repository.

The commit being backported was authored by Alexey Ivanov on 21 Mar 2024 and was reviewed by Phil Race, Tejesh R, Andrey Turbanov and Sergey Bylokhov.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk11u-dev:

$ git fetch https://github.com/openjdk-bots/jdk11u-dev.git backport-TheRealMDoerr-e66788c1-master:backport-TheRealMDoerr-e66788c1-master
$ git checkout backport-TheRealMDoerr-e66788c1-master
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk11u-dev.git backport-TheRealMDoerr-e66788c1-master

⚠️ @TheRealMDoerr You are not yet a collaborator in my fork openjdk-bots/jdk11u-dev. An invite will be sent out and you need to accept it before you can proceed.

Please sign in to comment.