Community
Participate
Working Groups
Build ID: I20080530-1730 This is probably a different issue than the bug 50639 of the same description... We have a background thread which creates images for consumption by the UI thread. In our scenario, we also have another resource used by these threads, around which we use locking (I'll call it "A"). It seems on Linux that running the display queue and creating an image both require a lock as well (I'll call it "D"). As a note, this works fine on both Windows and Mac - the "D" lock doesn't seem to exist in those platforms. The rough workflow breakdown: 1. A UI Thread event occurs which spawns our background thread 2. Our background thread starts up, locks resource "A". 3. UI thread continues executing UI events, comes across an event which requires resource "A", blocks on it. 4. Background thread tries to create image. This is where the deadlock occurs - Image.init(ImageData) line: 960 requires a lock which is currently owned by the display thread while it is processing events. 5. We're now in the scenario where the background thread owns "A" and is waiting for "D", while the UI thread owns "D" and is waiting for "A". Here are the relevant part of my stack traces: Thread [main] (Suspended) Unsafe.park(boolean, long) line: not available [native method] LockSupport.park(Object) line: not available AbstractQueuedSynchronizer$ConditionObject.awaitUninterruptibly() line: not available [local variables unavailable] [..Code that eventually requires lock on "A"..] EventTable.sendEvent(Event) line: 84 FigureCanvas(Widget).sendEvent(Event) line: 1154 FigureCanvas(Widget).sendEvent(int, Event, boolean) line: 1178 FigureCanvas(Widget).sendEvent(int, Event) line: 1163 FigureCanvas(Control).gtk_expose_event(int, int) line: 2650 FigureCanvas(Composite).gtk_expose_event(int, int) line: 667 FigureCanvas(Canvas).gtk_expose_event(int, int) line: 155 FigureCanvas(Widget).windowProc(int, int, int) line: 1535 FigureCanvas(Control).windowProc(int, int, int) line: 4448 Display.windowProc(int, int, int) line: 4096 OS._gtk_main_do_event(int) line: not available [native method] OS.gtk_main_do_event(int) line: 5783 Display.eventProc(int, int) line: 1175 OS._g_main_context_iteration(int, boolean) line: not available [native method] OS.g_main_context_iteration(int, boolean) line: 1541 Display.readAndDispatch() line: 3028 Workbench.runEventLoop(Window$IExceptionHandler, Display) line: 2382 Workbench.runUI() line: 2346 Workbench.access$4(Workbench) line: 2198 Workbench$5.run() line: 493 Realm.runWithDefault(Realm, Runnable) line: 288 Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 488 PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 149 Application.run(Object) line: 44 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available Method.invoke(Object, Object...) line: not available EclipseAppContainer.callMethodWithException(Object, String, Class[], Object[]) line: 574 EclipseAppHandle.run(Object) line: 195 EclipseAppLauncher.runApplication(Object) line: 110 EclipseAppLauncher.start(Object) line: 79 EclipseStarter.run(Object) line: 382 EclipseStarter.run(String[], Runnable) line: 179 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available Method.invoke(Object, Object...) line: not available Main.invokeFramework(String[], URL[]) line: 549 Main.basicRun(String[]) line: 504 Main.run(String[]) line: 1236 Main.main(String[]) line: 1212 Thread [Background-3] (Suspended) Object.wait(long) line: not available [native method] Lock(Object).wait() line: 485 Lock.lock() line: 34 OS.gdk_pixbuf_new(int, boolean, int, int, int) line: 3080 Image.init(ImageData) line: 960 Image.<init>(Device, ImageData) line: 400 ImageCreator.createImage() line: 60 [.. Code flow that acquires lock on "A" ..] ThreadPoolExecutor$Worker.runTask(Runnable) line: not available ThreadPoolExecutor$Worker.run() line: not available Thread.run() line: not available
You won't be able to wait inside call-in on GTK. SWT locks all access to the operating system on that platform using a single lock so that X Windows doesn't explode underneath when accessed from different threads. The lock is released just before SWT goes to sleep, allowing other threads to run. If you don't go back to sleep, then you can get deadlock. The work around is to run code in asyncExec() in the GUI thread in situations where this happens. I'm really sorry about this but given the underlying X Windows constraints, there just isn't a better solution.
Sorry, we WONTFIX this.