Bug 551303 - [GTK3] DND from SWT to embbedded AWT frame (SWT_AWT) is broken on Linux, application crashes in few minutes
Summary: [GTK3] DND from SWT to embbedded AWT frame (SWT_AWT) is broken on Linux, appl...
Status: REOPENED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.6   Edit
Hardware: PC Linux
: P3 normal with 4 votes (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-09-20 05:48 EDT by Serhiy Davydiuk CLA
Modified: 2023-12-27 08:30 EST (History)
6 users (show)

See Also:


Attachments
Crash file (82.41 KB, application/octet-stream)
2019-09-20 05:48 EDT, Serhiy Davydiuk CLA
no flags Details
Logs screen (129.10 KB, image/png)
2019-09-20 05:49 EDT, Serhiy Davydiuk CLA
no flags Details
Test application (3.05 KB, application/octet-stream)
2019-09-20 05:50 EDT, Serhiy Davydiuk CLA
no flags Details
Fedora 31, gtk 3.24 (6.95 KB, image/png)
2020-01-08 06:23 EST, Serhiy Davydiuk CLA
no flags Details
suggested solution (481 bytes, patch)
2020-03-24 07:18 EDT, Ilya Mykhaylov CLA
no flags Details | Diff
dnd animation window did not disposed properly (428 bytes, patch)
2020-03-27 10:14 EDT, Ilya Mykhaylov CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Serhiy Davydiuk CLA 2019-09-20 05:48:51 EDT
Created attachment 279949 [details]
Crash file

RedHat 7.4
GTK 3.22
OpenJDK 11.0.2

Create an SWT control and implement a DragSource for it (using SWT API), 
then create an embedded AWT frame and implement a DropTarget for AWT component (using AWT API).
 Drag and drop from SWT to AWT is broken: the AWT DropTarget does not receive drop events all the time. There are a lot of error messages from GTK and application crashes in few minutes (5-10m)

It's broken on GTK3, on GTK2 works fine. Tested versions: SWT 4.6-4.13. Java 8, OpenJDK 11.

Snippet to reproduce is below.
Run the app and DND the 1st button onto the 3rd one, look at the logs.

public static void main(String[] args) {

        Shell shell = new Shell(SWT.DIALOG_TRIM);
        shell.setLayout(new GridLayout(3, true));

        Button sourceButton = new Button(shell, SWT.PUSH);
        sourceButton.setText("Source");

        Button targetButton = new Button(shell, SWT.PUSH);
        targetButton.setText("SWT Target");

        Composite swingContainer = new Composite(shell, SWT.EMBEDDED);
        Frame frame = SWT_AWT.new_Frame(swingContainer);

        JButton swingButton = new JButton("Swing target");
        frame.add(swingButton);

        shell.open();
        shell.pack();

        DragSource ds = new DragSource(sourceButton, DND.DROP_MOVE);
        ds.setTransfer(new Transfer[] { TextTransfer.getInstance() });
        ds.addDragListener(new DragSourceAdapter() {
          @Override
          public void dragSetData(DragSourceEvent event) {
            event.data = "Hello";
          }
        });

        DropTarget dt = new DropTarget(targetButton, DND.DROP_MOVE);
        dt.setTransfer(new Transfer[] { TextTransfer.getInstance() });
        dt.addDropListener(new DropTargetAdapter() {
          @Override
          public void drop(DropTargetEvent event) {
            System.err.println("Drop success: " + event.data);
          }
        });

        java.awt.dnd.DropTarget awtdt = new java.awt.dnd.DropTarget(swingButton, new DropTargetListener() {

          @Override
          public void dropActionChanged(DropTargetDragEvent dtde) {
          }

          @Override
          public void drop(DropTargetDropEvent dtde) {
            dtde.acceptDrop(DnDConstants.ACTION_MOVE);
            System.err.println("drop " + dtde.getTransferable());
          }

          @Override
          public void dragOver(DropTargetDragEvent dtde) {

          }

          @Override
          public void dragExit(java.awt.dnd.DropTargetEvent dte) {

          }

          @Override
          public void dragEnter(DropTargetDragEvent dtde) {
            System.err.println("Drag enter");
          }
        });

        Display display = shell.getDisplay();
        while (!shell.isDisposed()) {
          if (!display.readAndDispatch()) {
            display.sleep();
          }
        }
      }

Crash log:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fe8f957ca03, pid=13753, tid=13754
#
# JRE version: OpenJDK Runtime Environment (11.0.2+9) (build 11.0.2+9)
# Java VM: OpenJDK 64-Bit Server VM (11.0.2+9, mixed mode, tiered, compressed oops, serial gc, linux-amd64)
# Problematic frame:
# C  [libgtk-3.so.0+0x3afa03]  gtk_drag_finish+0x23
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e %P %I %h" (or dumping to /home/serhii/Workspace/Testing/core.13753)
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

---------------  S U M M A R Y ------------

Command Line: -Dfile.encoding=UTF-8 DnDTest

Host: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz, 1 cores, 15G, CentOS Linux release 7.4.1708 (Core) 
Time: Thu Sep 19 07:03:44 2019 EDT elapsed time: 326 seconds (0d 0h 5m 26s)

---------------  T H R E A D  ---------------

Current thread (0x00007fe924010000):  JavaThread "main" [_thread_in_native, id=13754, stack(0x00007fe92d489000,0x00007fe92d58a000)]

Stack: [0x00007fe92d489000,0x00007fe92d58a000],  sp=0x00007fe92d5886e0,  free space=1021k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libgtk-3.so.0+0x3afa03]  gtk_drag_finish+0x23

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
J 658  org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(JZ)Z (0 bytes) @ 0x00007fe914759314 [0x00007fe9147592c0+0x0000000000000054]
J 1052 c2 org.eclipse.swt.widgets.Display.readAndDispatch()Z (77 bytes) @ 0x00007fe91478038c [0x00007fe914780160+0x000000000000022c]
j  DnDTest.main([Ljava/lang/String;)V+209
v  ~StubRoutines::call_stub

siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000004000000003
Comment 1 Serhiy Davydiuk CLA 2019-09-20 05:49:40 EDT
Created attachment 279950 [details]
Logs screen
Comment 2 Serhiy Davydiuk CLA 2019-09-20 05:50:05 EDT
Created attachment 279951 [details]
Test application
Comment 3 Eric Williams CLA 2019-09-20 11:35:47 EDT

*** This bug has been marked as a duplicate of bug 548661 ***
Comment 4 Serhiy Davydiuk CLA 2019-09-20 11:48:45 EDT
Hi Eric. It is not a duplicate. In my case DnD works but broken. Application crashes. Please see attachments
Comment 5 Serhiy Davydiuk CLA 2019-09-20 13:09:52 EDT
It is not a duplicate. In my case DnD works but broken. Application crashes. Please see attachments
Comment 6 Eric Williams CLA 2019-09-20 14:05:14 EDT
(In reply to Serhiy Davydiuk from comment #5)
> It is not a duplicate. In my case DnD works but broken. Application crashes.
> Please see attachments

Ah sorry I thought they were the same. Thanks for reopening.
Comment 7 Serhiy Davydiuk CLA 2019-12-09 09:13:54 EST
Thank you all for fixing https://bugs.eclipse.org/bugs/show_bug.cgi?id=548661. 
Is it possible to fix this defect too? I've tried to test using swt-4.14rc2 but the issue is still reproducible. Thanks
Comment 8 Serhiy Davydiuk CLA 2020-01-08 06:22:14 EST
I've tested the DnD behavior on RHEL 7.2 (gtk 3.14) and it works fine. I'm not sure is it related to gtk3 changes, like in this post https://stackoverflow.com/questions/56111131/drag-and-drop-issues-with-gtk3-20-and-later-desktop-gtk . <br>
Testing on Fedora 31 with gtk 3.24 failed, because SWT_AWT bridge seems broken (please see attachments)
Comment 9 Serhiy Davydiuk CLA 2020-01-08 06:23:09 EST
Created attachment 281410 [details]
Fedora 31, gtk 3.24
Comment 10 Eugene Bova CLA 2020-02-20 08:22:48 EST
What happens is that when drop is completed 
java.awt.dnd.DropTargetListener.drop(DropTargetDropEvent) gets called immediately, however drop source 
org.eclipse.swt.dnd.DragSourceListener.dragFinished(DragSourceEvent) is called by GTK with a delay of 5 mins. Because of the delay, I guess, gtk_drag_finish accesses a stale reference since by that time the context is invalid.

This behavior started appearing in GTK 3.19.7 after this commit
https://gitlab.gnome.org/GNOME/gtk/commit/bfee45e6f9f13506f97c8765255c7dc0dd698420
Though there are a few other commits before this one related to DnD as well.

Here is a note from 3.19.7 release notes:
 Drag-and-Drop has been rearchitected to move the input handling into
  GDK, where different backends can handle it according to their needs
  and capabilities. The new, 'managed' DND is currently implemented
  for X11 and Wayland.
Comment 11 Eugene Bova CLA 2020-03-11 12:19:50 EDT
gtk_drag_finish is called in a timeout handler (hardcoded to 5 mins)

Thread #28 [java] 2418 [core: 3] (Suspended : Breakpoint)	
	gtk_drag_finish() at gtkdnd.c:942 0x7f0260df5b09	
	gtk_drag_drop_finished() at gtkdnd.c:2,976 0x7f0260df5fbb	
	gtk_drag_abort_timeout() at gtkdnd.c:3,547 0x7f0260df6197	
	gdk_threads_dispatch() at gdk.c:720 0x7f026078ce78	
	g_timeout_dispatch() at 0x7f0221e10a7d	
	g_main_context_dispatch() at 0x7f0221e10049	
	g_main_context_iterate.isra.19() at 0x7f0221e103a8	
	g_main_context_iteration() at 0x7f0221e1045c	
	Java_org_eclipse_swt_internal_gtk_OS__1g_1main_1context_1iteration() at 0x7f0261428181	
	0x7f027c77f509	
	<...more frames...>	

There are 2 issues here:
1. Crash when handling timeout. 
   This needs be fixed in GTK.
   There is a bug in redhat with the same back trace.
   https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=1769799
2. gtk_drag_finish should be called without a timeout in the first place so that listeners should be notified in a timely manner.

After java.awt.dnd.DropTargetListener.drop(DropTargetDropEvent) is handled, AWT sends a ClientMessage via XSendEvent.
Then GDK receives an event from X11, emits GDK_DROP_FINISH event, dispatches it, and calls g_signal_emit_by_name (context, "dnd-finished") 
See gdk_dnd_handle_drop_finished() function in gdkdnd-x11.c. However no callback for this signal is invoked.
Comment 12 Ilya Mykhaylov CLA 2020-03-24 07:18:48 EDT
Created attachment 282205 [details]
suggested solution
Comment 13 Ilya Mykhaylov CLA 2020-03-24 07:22:16 EDT
The problem with proxy context and window that are created whenever we have swt -> swind dnd.
They did refactoring and they did not take into account such proxy changes. Before the chnage all such logic was handled by gtkdnd.c.
Now they moved some drop functions call to gdkdnd-x11.c. They connected the logic with gtkdnd.c by g_signal_connect (context, .....) functions.
The problem is that context is changed together with the proxy context and that's why finction gtk_drag_context_dnd_finished_cb is not called(the callback was registered with different context on drag start).

See attched patch.

Also I would suggest to take a look at gtk_drag_context_action_cb function which has never received right context that belongs to awt proxy.
Comment 14 Ilya Mykhaylov CLA 2020-03-27 10:14:48 EDT
Created attachment 282250 [details]
dnd animation window did not disposed properly

Another problem with dnd windows created under x11 contexts. These don't removed properly. As a result we have a lot of such windows after several dnd operations. Sucggested solution should resolve such problem.
Comment 15 Muhammad Bilal CLA 2023-12-27 08:30:18 EST
(In reply to Ilya Mykhaylov from comment #13)
> The problem with proxy context and window that are created whenever we have
> swt -> swind dnd.
> They did refactoring and they did not take into account such proxy changes.
> Before the chnage all such logic was handled by gtkdnd.c.
> Now they moved some drop functions call to gdkdnd-x11.c. They connected the
> logic with gtkdnd.c by g_signal_connect (context, .....) functions.
> The problem is that context is changed together with the proxy context and
> that's why finction gtk_drag_context_dnd_finished_cb is not called(the
> callback was registered with different context on drag start).
> 
> See attched patch.
> 
> Also I would suggest to take a look at gtk_drag_context_action_cb function
> which has never received right context that belongs to awt proxy.


ilyamykhayl@gmail.com Is the patch appropriate for adjusting SWT-AWT, or should it be upstreamed to the GTK repo? Do you have any plans to upstream your patches?

Can you reproduce this issue outside of SWT-AWT?