Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 339878 - Display(Device).dispose() can cause a deadlock
Summary: Display(Device).dispose() can cause a deadlock
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.7   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-14 08:46 EDT by Serge Beauchamp CLA
Modified: 2019-11-08 04:37 EST (History)
0 users

See Also:


Attachments
Possible fix (981 bytes, patch)
2011-03-14 08:52 EDT, Serge Beauchamp CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Serge Beauchamp CLA 2011-03-14 08:46:54 EDT
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;
    }
}
Comment 1 Serge Beauchamp CLA 2011-03-14 08:52:35 EDT
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?
Comment 2 Lars Vogel CLA 2019-11-08 04:37:03 EST
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.