-
Bug
-
Resolution: Unresolved
-
P4
-
11, 17, 24, 25
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
For the Apache NetBeans IDE errors were reported, that copy'n'paste with other applications on windows became unstable. The growing number of problems coincide with NetBeans removing its SecurityManager usage. The SecurityManager was used to inject a custom implementation of the clipboard, which was more robust regarding publishing and retrieving content from the system clipboard.
The problem the users observe are problems copying data from NetBeans to other processes. For a long time it was difficult to pin-point the problem until the user with the github handle @xxDark analyzed the problem and could trace it back into the WClipboard class/the native awt_Clipboard.cpp code. See details here:
https://github.com/apache/netbeans/discussions/7051#discussioncomment-12285535
It seems, that the core problem here is, that multiple threads can call into WClipboard#openClipboard and WClipboard#closeClipboard and thus end up with a clipboard already opened for a different or a clipboard being closed, while it should still be open.
As a prototype the user created a java agent, that ensured, that `handleContentsChanged` was serialized into the EDT, which seemed to fix the problem.
The test procedure was to run java code from the NetBeans IDE, that started an instance of notepad.exe and used java.awt.Robot to simulate text input into notepad.exe, simulated a copy-n-paste operation to netbeans, appenend the current iteration number in NetBeans to the pasted code and copy-n-pasted back to notepad. This code was run in a loop and several users reported, that they could reproduce the situation, where copies from NetBeans to notepad.exe ended with empty data pasted into notepad.
It was also observed, that when ran with a JDK built with fastdebug variant, assertions in the native code were hit.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Ensure a JDK is used, that is built with fastdebug configuration
2. Run the provided code with the fastdebug JDK from terminal using java.exe
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No assertions are hit.
ACTUAL -
Assertions in awt_Clipboard.cpp are hit:
- line 48
- line 136
- line 199
- line 284
---------- BEGIN SOURCE ----------
import java.awt.Toolkit;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.FlavorListener;
import java.awt.datatransfer.StringSelection;
import javax.swing.SwingUtilities;
public class Clipboardreproducer2 {
private static final System.Logger LOG = System.getLogger(Clipboardreproducer2.class.getName());
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(() -> {
Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(new FlavorListener() {
@Override
public void flavorsChanged(FlavorEvent e) {
LOG.log(System.Logger.Level.INFO, "Flavor Changed: {0} // {1}", e, SwingUtilities.isEventDispatchThread());
}
});
});
Runnable copy = new Runnable() {
@Override
public void run() {
try {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection("Test"), null);
LOG.log(System.Logger.Level.INFO, "Copy 1");
} catch (IllegalStateException ex) {
LOG.log(System.Logger.Level.ERROR, "Failed to invoke copy (1)", ex);
}
SwingUtilities.invokeLater(this);
}
};
SwingUtilities.invokeLater(copy);
Thread.sleep(60 * 1000);
System.exit(0);
}
}
---------- END SOURCE ----------
For the Apache NetBeans IDE errors were reported, that copy'n'paste with other applications on windows became unstable. The growing number of problems coincide with NetBeans removing its SecurityManager usage. The SecurityManager was used to inject a custom implementation of the clipboard, which was more robust regarding publishing and retrieving content from the system clipboard.
The problem the users observe are problems copying data from NetBeans to other processes. For a long time it was difficult to pin-point the problem until the user with the github handle @xxDark analyzed the problem and could trace it back into the WClipboard class/the native awt_Clipboard.cpp code. See details here:
https://github.com/apache/netbeans/discussions/7051#discussioncomment-12285535
It seems, that the core problem here is, that multiple threads can call into WClipboard#openClipboard and WClipboard#closeClipboard and thus end up with a clipboard already opened for a different or a clipboard being closed, while it should still be open.
As a prototype the user created a java agent, that ensured, that `handleContentsChanged` was serialized into the EDT, which seemed to fix the problem.
The test procedure was to run java code from the NetBeans IDE, that started an instance of notepad.exe and used java.awt.Robot to simulate text input into notepad.exe, simulated a copy-n-paste operation to netbeans, appenend the current iteration number in NetBeans to the pasted code and copy-n-pasted back to notepad. This code was run in a loop and several users reported, that they could reproduce the situation, where copies from NetBeans to notepad.exe ended with empty data pasted into notepad.
It was also observed, that when ran with a JDK built with fastdebug variant, assertions in the native code were hit.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Ensure a JDK is used, that is built with fastdebug configuration
2. Run the provided code with the fastdebug JDK from terminal using java.exe
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No assertions are hit.
ACTUAL -
Assertions in awt_Clipboard.cpp are hit:
- line 48
- line 136
- line 199
- line 284
---------- BEGIN SOURCE ----------
import java.awt.Toolkit;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.FlavorListener;
import java.awt.datatransfer.StringSelection;
import javax.swing.SwingUtilities;
public class Clipboardreproducer2 {
private static final System.Logger LOG = System.getLogger(Clipboardreproducer2.class.getName());
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(() -> {
Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(new FlavorListener() {
@Override
public void flavorsChanged(FlavorEvent e) {
LOG.log(System.Logger.Level.INFO, "Flavor Changed: {0} // {1}", e, SwingUtilities.isEventDispatchThread());
}
});
});
Runnable copy = new Runnable() {
@Override
public void run() {
try {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection("Test"), null);
LOG.log(System.Logger.Level.INFO, "Copy 1");
} catch (IllegalStateException ex) {
LOG.log(System.Logger.Level.ERROR, "Failed to invoke copy (1)", ex);
}
SwingUtilities.invokeLater(this);
}
};
SwingUtilities.invokeLater(copy);
Thread.sleep(60 * 1000);
System.exit(0);
}
}
---------- END SOURCE ----------
- links to
-
Review(master) openjdk/jdk/24614