Summary: | Threads deadlock in native keyboardfocus calls made form multiple threads | ||
---|---|---|---|
Product: | [JogAmp] Newt | Reporter: | Harvey Harrison <harvey.harrison> |
Component: | windows | Assignee: | Sven Gothel <sgothel> |
Status: | RESOLVED FIXED | ||
Severity: | critical | CC: | narf_bro |
Priority: | P1 | ||
Version: | 1 | ||
Hardware: | pc_x86_64 | ||
OS: | windows | ||
Type: | --- | SCM Refs: |
0be87f241c0f0b2f5881d9a602ce12378b8e453d
23697c7921039e9655a5760e21d7029598b679d7
d544c839f6df10f20977c786a446833f3aa7ef13
177d0da1a9a8e031f15efa9e89465f8ed97f25e5
|
Workaround: | --- | ||
Bug Depends on: | |||
Bug Blocks: | 892 | ||
Attachments: |
patch for discussion purposes, likely breaks things
Another workaround patch, tested on Java 6 and 7 on windows 7 |
(11:21:11 PM) sgothel: hmm .. the whole focus traversal .. (so you have an overview) .. in NewtCanvasAWT is to extend AWT's traversal w/ our NEWT child (11:21:41 PM) sgothel: I would love to see this fixed for sure (11:22:33 PM) hharrison: If there was a knob we could set without patching to just 'ignore keyboardfocus' we could also use that (11:24:06 PM) sgothel: we don't need to wait, i.e. the native calls explicitly state wait=false - b/c of this problem (11:24:20 PM) sgothel: so it is designed to be all deferred .. (11:25:08 PM) sgothel: the only problem is .. hmm is that the NEWT-EDT command waits for Component.requestFocus(Unknown Source) (11:25:42 PM) sgothel: after that .. if gives the focus back to NEWT (11:25:49 PM) sgothel: thats while it's waiting .. (11:25:59 PM) hharrison: and injecting events onto two queues feels...maybe like an even worse problem (11:26:08 PM) sgothel: so if the tail (give focus back to NEWT) would work on AWT-EDT .. maybe (11:26:19 PM) sgothel: as long it's all non-waiting (11:26:24 PM) sgothel: non-blocking (11:27:13 PM) sgothel: NewtCanvasAWT could inject a runnable to AWT-EDT to perform the AWT requestFocus() + action to call NEWT-EDT to focus NEWT window (non-blocking) (11:27:21 PM) sgothel: all non-blocking .. streaming (11:27:36 PM) sgothel: maybe we can try this .. (11:27:57 PM) sgothel: I look at it .. if it passes our unit tests .. good (11:28:16 PM) sgothel: and solves these issues Please provide a unit test - or a manual test case reproducing the dealock, so we can analyze the issue better and confirm the future change. Just wanted to comment that I am getting this as well, same call stack. Easy way to reproduce this is to put canvas.requestFocusInWindow() inside mouseClicked event on a MouseListener and then click away/into the window over and over. Same remedy (AWT-EDT task streaming) may apply to Bug 893. Created attachment 540 [details]
Another workaround patch, tested on Java 6 and 7 on windows 7
Again, mostly for discussion purposes.
Since we manage focus key traversal ourselves w/o requiring the AWT component to have the focus, it seems that we simply can drop requesting the focus. TestParentingFocus03KeyTraversalAWT: Works on X11 and Windows I have to double check this .. @@ -190,16 +190,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto if(DEBUG) { System.err.println("NewtCanvasAWT.FocusAction: "+Display.getThreadName()+", isOnscreen "+isOnscreen+", hasFocus "+hasFocus()+", isParent "+isParent+", isFS "+isFullscreen); } - if(isParent && !isFullscreen) { - // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus. - if(!hasFocus()) { - // Acquire the AWT focus 1st for proper AWT traversal - NewtCanvasAWT.super.requestFocus(); - } - if(isOnscreen) { - // Remove the AWT focus in favor of the native NEWT focus - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); - } + if( isParent && !isFullscreen && isOnscreen ) { + // Remove the AWT focus in favor of the native NEWT focus + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); } return false; // NEWT shall proceed requesting the native focus } (In reply to comment #6) > Since we manage focus key traversal ourselves w/o requiring the AWT > component to have the focus, Commit cb7118fc875b6722803e4b11d5681671962a8d3a introduced function to query the next or previous 'to be focused' component: AWTMisc.getNextFocus(..) .. etc. 0be87f241c0f0b2f5881d9a602ce12378b8e453d Since we manage focus key traversal ourselves w/o requiring the AWT component to have the focus[1], we simply can drop requesting the focus for 'focus hopping' NEWT -> AWT -> NEWT[2]. Further more, 'MenuSelectionManager.defaultManager().clearSelectedPath()' must be performed on AWT-EDT w/o blocking. Otherwise it may perform blocking tasks on AWT-EDT. [1] Commit cb7118fc875b6722803e4b11d5681671962a8d3a introduced function to query the next or previous 'to be focused' component: AWTMisc.getNextFocus(..) .. etc. [2] Focus hopping is also addressed in Bug 892 23697c7921039e9655a5760e21d7029598b679d7 NewtCanvasAWT.FocusAction must take focus when in offscreen-mode (OSX/CALayer) since the NEWT window _is_ offscreen (no input events) and AWT events are translated to NEWT. Regression of commit 0be87f241c0f0b2f5881d9a602ce12378b8e453d Running with commit d8f7418f170aba4703df2b11d5ae11598f71a796 I still see the following deadlock, I wonder, is there any harm in just firing a purpose built runnable into the AWT eventQueue to call the KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner() bit? "RenderThread-Display-.windows_nil-1-EDT-1" daemon prio=6 tid=0x0000000008f88000 nid=0x21c4 runnable [0x00000000115ae000] java.lang.Thread.State: RUNNABLE at sun.awt.KeyboardFocusManagerPeerImpl.getNativeFocusedWindow(Native Method) at sun.awt.KeyboardFocusManagerPeerImpl.getCurrentFocusedWindow(KeyboardFocusManagerPeerImpl.java:27) at java.awt.KeyboardFocusManager.getNativeFocusedWindow(KeyboardFocusManager.java:567) at java.awt.KeyboardFocusManager.markClearGlobalFocusOwner(KeyboardFocusManager.java:2496) - locked <0x00000007af1a4768> (a java.util.LinkedList) at java.awt.KeyboardFocusManager._clearGlobalFocusOwner(KeyboardFocusManager.java:550) at java.awt.KeyboardFocusManager.clearGlobalFocusOwner(KeyboardFocusManager.java:546) at com.jogamp.newt.awt.NewtCanvasAWT$FocusAction.run(NewtCanvasAWT.java:215) at jogamp.newt.WindowImpl.focusAction(WindowImpl.java:1920) at jogamp.newt.WindowImpl.requestFocus(WindowImpl.java:1892) at jogamp.newt.WindowImpl.requestFocus(WindowImpl.java:1888) at jogamp.newt.driver.windows.DisplayDriver.DispatchMessages0(Native Method) at jogamp.newt.driver.windows.DisplayDriver.dispatchMessagesNative(DisplayDriver.java:88) at jogamp.newt.DisplayImpl.dispatchMessages(DisplayImpl.java:540) at jogamp.newt.DisplayImpl$5.run(DisplayImpl.java:463) at jogamp.newt.DefaultEDTUtil$NEDT.run(DefaultEDTUtil.java:326) Locked ownable synchronizers: - None "AWT-EventQueue-0" prio=6 tid=0x0000000006da3800 nid=0x27c4 runnable [0x000000000c8bc000] java.lang.Thread.State: RUNNABLE at sun.awt.windows.WComponentPeer._requestFocus(Native Method) at sun.awt.windows.WComponentPeer.requestFocus(WComponentPeer.java:623) at java.awt.Component.requestFocusHelper(Component.java:7447) at java.awt.Component.requestFocusInWindow(Component.java:7330) at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:361) at java.awt.Component.dispatchEventImpl(Component.java:4525) at java.awt.Container.dispatchEventImpl(Container.java:2097) at java.awt.Window.dispatchEventImpl(Window.java:2482) at java.awt.Component.dispatchEvent(Component.java:4481) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:648) at java.awt.EventQueue.access$000(EventQueue.java:84) at java.awt.EventQueue$1.run(EventQueue.java:607) at java.awt.EventQueue$1.run(EventQueue.java:605) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98) at java.awt.EventQueue$2.run(EventQueue.java:621) at java.awt.EventQueue$2.run(EventQueue.java:619) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.awt.EventQueue.dispatchEvent(EventQueue.java:618) at java.awt.SequencedEvent.dispatch(SequencedEvent.java:101) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:646) at java.awt.EventQueue.access$000(EventQueue.java:84) at java.awt.EventQueue$1.run(EventQueue.java:607) at java.awt.EventQueue$1.run(EventQueue.java:605) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98) at java.awt.EventQueue$2.run(EventQueue.java:621) at java.awt.EventQueue$2.run(EventQueue.java:619) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.awt.EventQueue.dispatchEvent(EventQueue.java:618) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Locked ownable synchronizers: - None "AWT-Windows" daemon prio=6 tid=0x0000000006d85000 nid=0x17a4 waiting for monitor entry [0x000000000844e000] java.lang.Thread.State: BLOCKED (on object monitor) at java.awt.KeyboardFocusManager.shouldNativelyFocusHeavyweight(KeyboardFocusManager.java:2304) - waiting to lock <0x00000007af1a4768> (a java.util.LinkedList) at sun.awt.windows.WToolkit.eventLoop(Native Method) at sun.awt.windows.WToolkit.run(WToolkit.java:293) at java.lang.Thread.run(Thread.java:662) Locked ownable synchronizers: - None Patch I've been hammering on this morning that seems to be holding up: diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 49bd0d7..56da037 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -212,8 +212,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto if( isParent && !isFullscreen ) { // must be parent of newtChild _and_ newtChild not fullscreen if( isOnscreen ) { // Remove the AWT focus in favor of the native NEWT focus - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); - } else if( !isOnscreen ) { + AWTEDTExecutor.singleton.invoke(false, new ClearFocusOwner()); + } + else { // In offscreen mode we require the focus! if( !hasFocus() ) { // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus. @@ -226,8 +227,16 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } private final FocusAction focusAction = new FocusAction(); + private static class ClearFocusOwner implements Runnable { + @Override + public void run() { + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + } + } + Commits available at https://github.com/AusencoSimulation/jogl.git commit d544c839f6df10f20977c786a446833f3aa7ef13 Author: Harvey Harrison <harvey.harrison@gmail.com> Date: Mon Nov 18 10:54:35 2013 -0800 jogl: do the clearGlobalFocusOwner() call on the AWT EDT in NewtCanvasAWT Otherwise we can deadlock in the native focusrequest calls from the AWT thread, see bug 879 for the details. Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com> commit 0a9d16f057727652220a5983b65f22f427df6a22 Author: Harvey Harrison <harvey.harrison@gmail.com> Date: Mon Nov 18 10:55:30 2013 -0800 jogl: simplify conditional that repeats test for isOnScreen if (isOnscreen) else if (!isOnScreen) change to if (isOnscreen) else Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com> commit 417675219de9fb5fceca5771812366ae8768b658 Author: Harvey Harrison <harvey.harrison@gmail.com> Date: Mon Nov 18 10:54:01 2013 -0800 jogl: add missing @Override annotation in NewtCanvasAWT Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com> added Harvey's git-sha1 values to SCM Refs. field. |
Created attachment 531 [details] patch for discussion purposes, likely breaks things Stack dumps once everthing locks up, the RenderThread stays in the _requestFocus native method forever at this point. "RenderThread-Display-.windows_nil-1-EDT-1" daemon prio=6 tid=0x000000000f622000 nid=0xe6c runnable [0x000000001417e000] java.lang.Thread.State: RUNNABLE at sun.awt.windows.WComponentPeer._requestFocus(Native Method) at sun.awt.windows.WComponentPeer.requestFocus(Unknown Source) at java.awt.Component.requestFocusHelper(Unknown Source) at java.awt.Component.requestFocusHelper(Unknown Source) at java.awt.Component.requestFocus(Unknown Source) at com.jogamp.newt.awt.NewtCanvasAWT.access$301(NewtCanvasAWT.java:83) at com.jogamp.newt.awt.NewtCanvasAWT$FocusAction.run(NewtCanvasAWT.java:179) at jogamp.newt.WindowImpl.focusAction(WindowImpl.java:1789) at jogamp.newt.WindowImpl.requestFocus(WindowImpl.java:1761) at jogamp.newt.WindowImpl.requestFocus(WindowImpl.java:1757) at jogamp.newt.driver.windows.DisplayDriver.DispatchMessages0(Native Method) at jogamp.newt.driver.windows.DisplayDriver.dispatchMessagesNative(DisplayDriver.java:85) at jogamp.newt.DisplayImpl.dispatchMessages(DisplayImpl.java:496) at jogamp.newt.DisplayImpl$5.run(DisplayImpl.java:419) at jogamp.newt.DefaultEDTUtil$EventDispatchThread.run(DefaultEDTUtil.java:308) Locked ownable synchronizers: - None "AWT-EventQueue-0" prio=6 tid=0x0000000009aa1800 nid=0x27e0 runnable [0x000000000daec000] java.lang.Thread.State: RUNNABLE at sun.awt.KeyboardFocusManagerPeerImpl.getNativeFocusedWindow(Native Method) at sun.awt.KeyboardFocusManagerPeerImpl.getCurrentFocusedWindow(Unknown Source) at java.awt.KeyboardFocusManager.getNativeFocusedWindow(Unknown Source) at java.awt.KeyboardFocusManager.markClearGlobalFocusOwner(Unknown Source) - locked <0x000000075a9026a8> (a java.util.LinkedList) at java.awt.KeyboardFocusManager._clearGlobalFocusOwner(Unknown Source) at java.awt.KeyboardFocusManager.clearGlobalFocusOwner(Unknown Source) at jogamp.newt.awt.event.AWTParentWindowAdapter.focusGained(AWTParentWindowAdapter.java:75) at java.awt.Component.processFocusEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source) at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source) at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$000(Unknown Source) at java.awt.EventQueue$1.run(Unknown Source) at java.awt.EventQueue$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.SequencedEvent.dispatch(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$000(Unknown Source) at java.awt.EventQueue$1.run(Unknown Source) at java.awt.EventQueue$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source) Locked ownable synchronizers: - None "AWT-Windows" daemon prio=6 tid=0x0000000007b71000 nid=0x1418 waiting for monitor entry [0x0000000009ebe000] java.lang.Thread.State: BLOCKED (on object monitor) at java.awt.KeyboardFocusManager.shouldNativelyFocusHeavyweight(Unknown Source) - waiting to lock <0x000000075a9026a8> (a java.util.LinkedList) at sun.awt.windows.WToolkit.eventLoop(Native Method) at sun.awt.windows.WToolkit.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Locked ownable synchronizers: - None