Community
Participate
Working Groups
Shutting down the workbench can cause a deadlock in Display(Device).dispose() when a runnable scheduled to be executed on the main thread event loop (with Display.asyncExec()) happens to be executed within the Display.release() method, while the Device lock is held. This can happen based on a race condition when the user shutdowns the workbench at the 'wrong' time. Example of this deadlock: Thread [main] (Suspended) owns: LaunchConfigurationWorkingCopy (id=25997) owns: RunnableLock (id=25998) owns: Class<T> (org.eclipse.swt.graphics.Device) (id=16058) waiting for: OrderedLock (id=25999) owned by: Thread [Worker-3] (Suspended) waiting for: Class<T> (org.eclipse.swt.graphics.Device) (id=16058) OrderedLock.createSemaphore() line: 142 XXXXXXXXXXXXXXXXXXXX OrderedLock.acquire(long) line: 100 OrderedLock.acquire() line: 82 WorkManager.endUnprotected(int) line: 181 Workspace.run(IWorkspaceRunnable, ISchedulingRule, int, IProgressMonitor) line: 1984 LaunchConfigurationWorkingCopy.doSave(IProgressMonitor) line: 218 LaunchConfigurationWorkingCopy.doSave() line: 178 LaunchUtils.saveLaunchConfig(ILaunchConfigurationWorkingCopy, boolean) line: 62 MulticoreManager.handleHostUpdate(CWHost, ILaunchConfiguration) line: 721 MulticoreManager.handleSystemModelResourceChanged(ISystemModelChangeEvent) line: 317 StartupPlugin$1.systemModelResourceChanged(ISystemModelChangeEvent) line: 40 SystemModelChangeEventManager.notify(ISystemModelChangeEvent) line: 84 SystemRegistry.fireModelChangeEvent(int, int, Object, String) line: 2554 SystemRegistry$FireNewHostEvents.run() line: 1837 RunnableLock.run() line: 35 UISynchronizer(Synchronizer).runAsyncMessages(boolean) line: 134 Display.runAsyncMessages(boolean) line: 3959 Display.readAndDispatch() line: 3580 Display.release() line: 3631 Display(Device).dispose() line: 293 XXXXXXXXXXXXXXXXXXXX IDEApplication.start(IApplicationContext) line: 129 UITestApplication.start(IApplicationContext) line: 46 EclipseAppHandle.run(Object) line: 193 EclipseAppLauncher.runApplication(Object) line: 110 EclipseAppLauncher.start(Object) line: 79 EclipseStarter.run(Object) line: 386 EclipseStarter.run(String[], Runnable) line: 179 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 Method.invoke(Object, Object...) line: 597 Main.invokeFramework(String[], URL[]) line: 550 Main.basicRun(String[]) line: 505 Main.run(String[]) line: 1237 Main.main(String[]) line: 1213 Owns : Device.class public void dispose () { synchronized (Device.class) { if (isDisposed()) return; checkDevice (); release (); waits to aquire: OrderedLock (id=25999) private synchronized Semaphore createSemaphore() { return attempt() ? null : enqueue(new Semaphore(Thread.currentThread())); } Worker 3: Thread [Worker-3] (Suspended) owns: OrderedLock (id=25999) waiting for: Class<T> (org.eclipse.swt.graphics.Device) (id=16058) owned by: Thread [main] (Suspended) Display(Device).isDisposed() line: 802 XXXXXXXXXXXXXXXXXXXX UILockListener.isUI() line: 174 UILockListener.aboutToRelease() line: 111 LockManager.aboutToRelease() line: 92 OrderedLock.doRelease() line: 191 XXXXXXXXXXXXXXXXXXXX OrderedLock.release() line: 245 WorkManager.beginUnprotected() line: 102 LaunchManager$4(InternalWorkspaceJob).run(IProgressMonitor) line: 37 Worker.run() line: 55 owns: private synchronized void doRelease() waits to aquire: public boolean isDisposed () { synchronized (Device.class) { return disposed; } }
Created attachment 191107 [details] Possible fix One solution is to empty the runnable queue right before going in the Device.dispose() method, and acquiring the Device lock. Clients could still queue runnables while the Device.dispose() and Display.release() code is executed, although this would typically happen because of handling the DISPOSE event, which should then be prepared to run while the Device lock is acquired. This is the best fix I found while maintaining backward compatibility. The patch would need to be applied to each Display.java for the respective platforms. What do you guys think?
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. If the bug is still relevant please remove the stalebug whiteboard tag.