Bug 567578 - Fix Invalid Thread Access
Wrap execution into a runnable and execute it directly if possible to
not cause side effects to existing code (eg., tests).
Change-Id: I702722e290bc4b46636177653e67522369b1823a
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/packageview/PackageExplorerPart.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/packageview/PackageExplorerPart.java
index 6281a20..de86f00 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/packageview/PackageExplorerPart.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/packageview/PackageExplorerPart.java
@@ -109,6 +109,7 @@
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.manipulation.MembersOrderPreferenceCacheCommon;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.IPackagesViewPart;
@@ -125,8 +126,8 @@
import org.eclipse.jdt.internal.ui.dnd.JdtViewerDropSupport;
import org.eclipse.jdt.internal.ui.filters.OutputFolderFilter;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
-import org.eclipse.jdt.internal.ui.preferences.MembersOrderPreferenceCache;
import org.eclipse.jdt.internal.ui.util.JavaUIHelp;
+import org.eclipse.jdt.internal.ui.util.SWTUtil;
import org.eclipse.jdt.internal.ui.util.SelectionUtil;
import org.eclipse.jdt.internal.ui.viewsupport.AppearanceAwareLabelProvider;
import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
@@ -1189,23 +1190,25 @@
if (fViewer == null)
return;
- boolean refreshViewer= false;
+ SWTUtil.execDirectOrAsyncIfNecessary(fViewer::getControl, ()-> {
+ boolean refreshViewer= false;
- if (PreferenceConstants.SHOW_CU_CHILDREN.equals(event.getProperty())) {
- boolean showCUChildren= PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.SHOW_CU_CHILDREN);
- ((StandardJavaElementContentProvider)fViewer.getContentProvider()).setProvideMembers(showCUChildren);
+ if (PreferenceConstants.SHOW_CU_CHILDREN.equals(event.getProperty())) {
+ boolean showCUChildren= PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.SHOW_CU_CHILDREN);
+ ((StandardJavaElementContentProvider)fViewer.getContentProvider()).setProvideMembers(showCUChildren);
- refreshViewer= true;
- } else if (MembersOrderPreferenceCache.isMemberOrderProperty(event.getProperty())) {
- refreshViewer= true;
- } else if (PreferenceConstants.APPEARANCE_SORT_LIBRARY_ENTRIES_BY_NAME.equals(event.getProperty())) {
- // set new comparator, since it might evaluate this property on construction
- setComparator();
- refreshViewer = true;
- }
+ refreshViewer= true;
+ } else if (MembersOrderPreferenceCacheCommon.isMemberOrderProperty(event.getProperty())) {
+ refreshViewer= true;
+ } else if (PreferenceConstants.APPEARANCE_SORT_LIBRARY_ENTRIES_BY_NAME.equals(event.getProperty())) {
+ // set new comparator, since it might evaluate this property on construction
+ setComparator();
+ refreshViewer = true; // is this really necessary? setComparator() calls refresh if the comparator changes
+ }
- if (refreshViewer)
- fViewer.refresh();
+ if (refreshViewer)
+ fViewer.refresh();
+ });
}
@Override
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/util/SWTUtil.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/util/SWTUtil.java
index c1889f9..b1c76e2 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/util/SWTUtil.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/util/SWTUtil.java
@@ -13,6 +13,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.ui.util;
+import java.util.function.Supplier;
+
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
@@ -25,6 +27,7 @@
import org.eclipse.swt.widgets.Caret;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;
@@ -38,6 +41,8 @@
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.ui.PlatformUI;
+
/**
* Utility class to simplify access to some SWT resources.
@@ -168,6 +173,32 @@
textField.setBackground(textField.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
}
+ /**
+ * Executes a given runnable directly if this thread is the UI thread or submits the runnable
+ * to {@link Display#asyncExec(Runnable)} of the provided control otherwise.
+ * <p>
+ * The control will be checked for {@link Control#isDisposed()} before executing the runnable.
+ *
+ * @param supplier supplier for a {@link Control} to use
+ * @param r the runnable
+ */
+ public static void execDirectOrAsyncIfNecessary(Supplier<Control> supplier, Runnable r) {
+ if(Display.getCurrent() != null) {
+ Control ctrl = supplier.get();
+ if (ctrl != null && !ctrl.isDisposed()) {
+ r.run();
+ }
+ } else {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
+ Control ctrl = supplier.get();
+ if (ctrl != null && !ctrl.isDisposed()) {
+ r.run();
+ }
+ });
+ }
+
+ }
+
private SWTUtil() {
}