eclipse / chemclipse

ChemClipse Project
Eclipse Public License 1.0
39 stars 18 forks source link

Getting the active Shell crashes now #160

Closed eselmeister closed 4 years ago

eselmeister commented 4 years ago

When e.g. running the following chromatogram processors, an exception is thrown now:

It crashes when trying to get the Shell:

            Shell shell = DisplayUtils.getShell();
            if(shell != null) {
                PeakDetectorSupport peakDetectorSupport = new PeakDetectorSupport();
                peakDetectorSupport.addPeaks(shell, processSettings);
            } else {
                WizardRunnable wizardRunnable = new WizardRunnable(processSettings);
                DisplayUtils.getDisplay().syncExec(wizardRunnable);
            }

The following error is thrown:

ERROR ModalContext workbench.DisplayUtils.getShell (DisplayUtils.java:84) Invalid thread access
org.eclipse.swt.SWTException: Invalid thread access
    at org.eclipse.swt.SWT.error(SWT.java:4533)
    at org.eclipse.swt.SWT.error(SWT.java:4448)
    at org.eclipse.swt.SWT.error(SWT.java:4419)
    at org.eclipse.swt.widgets.Display.error(Display.java:1236)
    at org.eclipse.swt.widgets.Display.checkDevice(Display.java:815)
    at org.eclipse.swt.widgets.Display.getActiveShell(Display.java:1450)
    at org.eclipse.chemclipse.support.ui.workbench.DisplayUtils.getShell(DisplayUtils.java:82)
    at net.openchrom.xxd.process.supplier.templates.ui.core.PeakDetectorMSD.detect(PeakDetectorMSD.java:39)
    at net.openchrom.xxd.process.supplier.templates.ui.core.PeakDetectorMSD.detect(PeakDetectorMSD.java:55)
    at org.eclipse.chemclipse.chromatogram.msd.peak.detector.core.PeakDetectorMSD.detect(PeakDetectorMSD.java:104)
    at org.eclipse.chemclipse.chromatogram.msd.peak.detector.core.PeakDetectorMSD.detect(PeakDetectorMSD.java:97)
    at org.eclipse.chemclipse.chromatogram.msd.peak.detector.core.PeakDetectorMSDProcessTypeSupplier$PeakDetectorProcessorSupplier.apply(PeakDetectorMSDProcessTypeSupplier.java:76)
    at org.eclipse.chemclipse.chromatogram.msd.peak.detector.core.PeakDetectorMSDProcessTypeSupplier$PeakDetectorProcessorSupplier.apply(PeakDetectorMSDProcessTypeSupplier.java:1)
    at org.eclipse.chemclipse.model.supplier.ChromatogramSelectionProcessorSupplier.apply(ChromatogramSelectionProcessorSupplier.java:39)
    at org.eclipse.chemclipse.model.supplier.IChromatogramSelectionProcessSupplier$1.execute(IChromatogramSelectionProcessSupplier.java:54)
    at org.eclipse.chemclipse.processing.supplier.IProcessSupplier.applyProcessor(IProcessSupplier.java:142)
    at org.eclipse.chemclipse.ux.extension.xxd.ui.swt.editors.ProcessorSupplierMenuEntry$1.run(ProcessorSupplierMenuEntry.java:88)
    at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:119)

The DisplayUtils class has been improved, which might need additional checks:

    if(shell == null) {
            if(display != null) {
                Shell[] shells = display.getShells();
                for(Shell s : shells) {
                    if(s.isDisposed() || !s.isVisible()) {
                        continue;
                    }
                    Object ignoreDialog = s.getData("org.eclipse.e4.ui.ignoreDialog");
                    if(ignoreDialog instanceof Boolean && (Boolean)ignoreDialog) {
                        continue;
                    }
                    return s;
                }
            }
            logger.error("Shell is null!");
        }
laeubi commented 4 years ago

Invalid thread access means that code is calling UI-Method from the wrong Thread (e.g. application or background thread) and not from UI-Thread. This is an error of the caller and would normally result in never getting a shell at all. Dsiplay.getCurrent().asyncExec/syncExec must be called to make ensure code is running on UI thread.

laeubi commented 4 years ago

Display.getCurrent() == null could be used to check if on UI thread.

kerner1000 commented 4 years ago

maybe a convenience method like executeInUIThread(Runnable) would be useful? This could check if we are already on UI thread and if not, it could call Dsiplay.getCurrent().asyncExec/syncExec