Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 341799

Summary: SWT and AWT/Swing need to synchronize access to GTK
Product: [Eclipse Project] Platform Reporter: Silenio Quarti <Silenio_Quarti>
Component: SWTAssignee: Platform-SWT-Inbox <platform-swt-inbox>
Status: RESOLVED WONTFIX QA Contact:
Severity: normal    
Priority: P3 CC: akurtakov, alex.thibodeau, artem.ananiev, arunkumar.thondapu, btickets, bugs.eclipse.org, egil, mseele, pwebster, rajatjain840, remy.suen, sebastien.schneider, simon.templer
Version: 3.7   
Target Milestone: ---   
Hardware: PC   
OS: Linux-GTK   
Whiteboard:
Bug Depends on:    
Bug Blocks: 298113    

Description Silenio Quarti CLA 2011-04-04 10:59:49 EDT
SWT and AWT/swing (if the GTK L&F is used) are both making GTK function calls. They both have locks to protect there own threads from accessing GTK concurrently.  AWT uses the GTK lock (gdk_threads_enter()/gdk_threads_leave()). SWT uses its own locking, because the GTK lock is not reentrant.

In order to make both toolkits synchronize access to GTK/X, they need to use a single lock. The obvious choice is to use the GTK lock, but this has been proven to be impossible because that lock is not reentrant. It is fairly easy to have a deadlock even in a single threaded program. See bug#280649 and bug#341085 for examples.

One possible solution is to make the GTK lock reentrant by calling gdk_threads_set_locking_functions(). This has to be done by both toolkits before the call to gdk_threads_init().
Comment 1 Silenio Quarti CLA 2011-04-04 11:05:43 EDT
Hi Artem, is the solution I mentioned above reasonable?
Comment 2 Silenio Quarti CLA 2011-04-04 11:09:30 EDT
Solving this bug would also help bug#139468.
Comment 3 Artem Ananiev CLA 2011-04-05 07:09:59 EDT
I haven't looked through all the GTK calls in AWT/Swing, but I suspect we don't need GTK lock reentrancy. As far as I understand your suggestion, the changes are only required at SWT side, correct? All they need is to introduce their own reentrant wrappers over standard GTK lock (which is used in gdk_threads_enter/leave, which are already called by AWT) and set them via gdk_threads_set_lock_functions, is this correct?
Comment 4 Silenio Quarti CLA 2011-04-05 11:33:32 EDT
(In reply to comment #3)
> I haven't looked through all the GTK calls in AWT/Swing, but I suspect we don't
> need GTK lock reentrancy. As far as I understand your suggestion, the changes
> are only required at SWT side, correct? 

AWT/Swing would need the reentrant lock only if it was calling the GTK event loop calls. My guess is that is not the case. SWT uses those calls.

> All they need is to introduce their own
> reentrant wrappers over standard GTK lock (which is used in
> gdk_threads_enter/leave, which are already called by AWT) and set them via
> gdk_threads_set_lock_functions, is this correct?

Yes, that is all that is necessary. The wrappers are set in the initialization of both toolkits and gdk_threads_enter/leave() are used to lock around GTK calls.   SWT does not make these calls (enter/leave) directly today. So there are more changes in the SWT side. I believe AWT is already calling enter/leave, given that it initializes gtk threads by calling gdk_threads_init().

The wrapper functions could use a GStaticRecMutex. The enter_fn would call g_static_rec_mutex_lock() and the leave_fn would call g_static_rec_mutex_unlock().
Comment 5 Artem Ananiev CLA 2011-04-06 03:54:20 EDT
> AWT/Swing would need the reentrant lock only if it was calling the GTK event
> loop calls. My guess is that is not the case. SWT uses those calls.

Correct. AWT/Swing don't use GTK event loops.

> Yes, that is all that is necessary. The wrappers are set in the initialization
> of both toolkits and gdk_threads_enter/leave() are used to lock around GTK
> calls.   SWT does not make these calls (enter/leave) directly today. So there
> are more changes in the SWT side. I believe AWT is already calling enter/leave,
> given that it initializes gtk threads by calling gdk_threads_init().

Correct. AWT/Swing already has gdk_threads_enter/leave calls.
Comment 6 Silenio Quarti CLA 2011-04-07 10:55:24 EDT
Another related problem bug#341538.
Comment 7 Alex Thibodeau CLA 2012-09-26 14:15:06 EDT
I'm also hitting this problem I believe on Solaris X86 using the Java Desktop Environment.

Our application will hang either in the SWT OS.<insert native method here> or in the GTKNativeStyle.native_get_xthickness(int). Has there been any progress on this?
Comment 8 Alex Thibodeau CLA 2012-10-04 10:47:58 EDT
I was able to resolve my issue by sshing into the workstation I was using from the same workstation. Only problem is I have no idea why this works...

(In reply to comment #7)
> I'm also hitting this problem I believe on Solaris X86 using the Java
> Desktop Environment.
> 
> Our application will hang either in the SWT OS.<insert native method here>
> or in the GTKNativeStyle.native_get_xthickness(int). Has there been any
> progress on this?
Comment 9 Simon Templer CLA 2012-11-22 11:04:32 EST
It seems this problem is causing the JVM to crash when running my RCP application on Linux (No problems at all on Windows). I have a Swing component embedded in a view through the SWT_AWT bridge, opening the view usually results in a VM crash, most of the time with no error message, but if I get one, it's the following:

[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
java: ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Comment 10 James Fry CLA 2012-11-22 13:07:40 EST
(In reply to comment #9)
> It seems this problem is causing the JVM to crash when running my RCP
> application on Linux (No problems at all on Windows). I have a Swing
> component embedded in a view through the SWT_AWT bridge, opening the view
> usually results in a VM crash, most of the time with no error message, but
> if I get one, it's the following:

IIRC, an ugly workaround for this is to specify any Swing L&F other than the GTK one - eg -Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel on the launcher config for Linux.

I don't have a Linux box to hand to verify, but I think it is what we have on our products to work around the issue.
Comment 11 Simon Templer CLA 2012-11-23 05:25:46 EST
(In reply to comment #10)
> IIRC, an ugly workaround for this is to specify any Swing L&F other than the
> GTK one - eg -Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel on
> the launcher config for Linux.
> 
> I don't have a Linux box to hand to verify, but I think it is what we have
> on our products to work around the issue.

Thank you very much for the hint, James!
I tested it and the workaround indeed prevents the JVM crash when the view with the embedded Swing component is shown.
Comment 12 Rajat Jain CLA 2012-11-27 09:50:41 EST
Anybody able to solve this bug without setting vm-args ?
I have a web start application going through this same difficult phase and I can't set JAVAWS_VM_ARGS swing.defaultlaf inside jnlp .
Comment 13 Simon Templer CLA 2012-11-27 10:02:07 EST
(In reply to comment #12)
> Anybody able to solve this bug without setting vm-args ?
> I have a web start application going through this same difficult phase and I
> can't set JAVAWS_VM_ARGS swing.defaultlaf inside jnlp .

I use a specific class extended from composite everywhere I embed a Swing component. On creation it first calls a method similar to this to initialize the look and feel programmatically:

public static void setupLookAndFeel() {
  if (!lafInitialized) {
    try {
      if (Platform.WS_GTK.equals(Platform.getWS())) {
        // Eclipse Bug 341799 workaround
        UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
      }
      else {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      }
    } catch (Exception e) {
      _log.error(...)
    }
    lafInitialized = true;
  }
}
Comment 14 Michael Seele CLA 2015-04-22 03:25:58 EDT
Anybody working on this problem?
In my opinion this is a Blocker for SWT with Java Web Start under Linux.
There is no chance to set the JAVAWS_VM_ARGS on a client's pc (they get the jnlp URL and that's it).
Comment 15 Alexander Kurtakov CLA 2019-01-30 06:50:37 EST
GTK 4 removes gdk_threads* functions thus closing this one as wontfix as "All GDK and GTK+ calls should be made from the main thread" according to Gtk devs.