Greetings,
I am able to consitently get imagej to lock up, and I am a loss at what I am directly or indirectly doing to cause this. The scenario is: my plugin DICOM_open creates a GenericDialog with an addDialogListener, which displays and after showDialog returns opens a set of DICOM files as a hyperstack. After this I run another plugin, Diffusion_Multimodal, which creates a GenericDialog and after the showDialog processes this hyperstack creating a set of images in windows; these windows have listeners - method that add and removes listener is below. Closing the hyperstack and running DICOM_open again causes imagej to lockup within showDialog, see first entry in thread stack traces. I can run DICOM_open only, over and over again, without any lockup. I can run Diffusion_Multimodal, after the first DICOM_open, over and over again without any lockup. Although, running DICOM_open after Diffusion_Multimodal lockups everytime. I have run this code lots and lots in the past and do not remember this scenario ever happening. I discovered this on release 1.52u14 and confirmed it still happens on 1.53e14. Any insites and / or suggestion on how to debug this would be greatly appriciated. Thanks in advance, Fred relevant code from DICOM_open.run =============== DirectoryChooser dc = new DirectoryChooser("Select Root Directory of your DICOM datasets"); String sdir = dc.getDirectory(); IJ.log("sdir = "+sdir); if (sdir == null) return; path = new File(sdir); loc = (Point)IJ.getProperty("PreferedLocation"); GenericDialog gd = new GenericDialog("Select DICOM dataset"); IJ.log("GenericDialog new"); if (loc != null) gd.setLocation(loc.x, loc.y); gd.addMessage(path.getAbsolutePath(), new Font("Monospaced", Font.BOLD, 12)); where = (Label)gd.getMessage(); IJ.log("GenericDialog Choice"); gd.addChoice("", scan(path),""); which = (Choice)gd.getChoices().get(0); gd.addToSameRow(); gd.addCheckbox("Info",false); ((Checkbox)gd.getCheckboxes().get(0)).setEnabled(false); gd.addMessage(padR("Subject",50)+"\n"+ padR("Date",50)+"\n"+ padR("Description",50), new Font("Monospaced", Font.BOLD, 12)); info = (MultiLineLabel)gd.getMessage(); updateFields(path); IJ.log("GenericDialog Choice"); gd.addChoice("Diffusion", new String[]{"<Nope>","Trace","X", "Y", "Z"},"<Nope>"); diff = (Choice)gd.getChoices().get(1); gd.addToSameRow(); gd.addStringField("Var",""); gd.addToSameRow(); gd.addStringField("Tag","",10); var = (TextField)gd.getStringFields().get(0); tag = (TextField)gd.getStringFields().get(1); gd.addRadioButtonGroup("Format:", new String[]{"Float","Scaled", "16-bit fixed", "16-bit broken"}, 1, 4, "16-bit fixed"); gd.addDialogListener(this); gd.setOKLabel("Tell Me More"); IJ.log("GenericDialog showDialog"); gd.showDialog(); if (gd.wasCanceled()) return; =============== assumed relevant code from Diffusion_Multimodal: =============== private void setupPlotting(ImagePlus imp, ImagePlus[] Rimps) { imp.getWindow().addWindowListener(this); imp.getWindow().getCanvas().addMouseListener(this); imp.getWindow().getCanvas().addMouseMotionListener(this); imp.getWindow().getCanvas().addKeyListener(this); engaged = true; for(ImagePlus rimp : Rimps) rimp.setZ(imp.getZ()); for(ImagePlus rimp : Rimps) rimp.getWindow().addWindowListener(this); } boolean engaged = false; void disengage(ImageWindow iw) { if (!engaged) return; if (Rimps == null) { IJ.log("MultiModal_diffusion.disengage called with Rimps == null"); return; } boolean oneOfUs = false; for(ImagePlus imp : Rimps) if (iw.getImagePlus() == imp) oneOfUs = true; if (!oneOfUs) return; if (dimp == null) IJ.showStatus("diffusion_MultiModal disengage DWI null"); else { dimp.getWindow().getCanvas().removeMouseListener(this); dimp.getWindow().getCanvas().removeMouseMotionListener(this); dimp.getWindow().getCanvas().removeKeyListener(this); dimp.getWindow().removeWindowListener(this); engaged = false; IJ.showStatus("Multimodal Diffusion Disengaged"); IJ.log("Multimodal Diffusion Disengaged"); } if (Rimps != null) { for(ImagePlus rimp : Rimps) rimp.getWindow().removeWindowListener(this); for(ImagePlus imp : Rimps) { IJ.log("Closing: "+imp.getTitle()); if (imp != null && imp.getWindow() != null) imp.getWindow().close(); } } for(int i=0; i<pwv.size(); i++) pwv.get(i).close(); } =============== $ imagej -x2048 Image display and analysis program. Opens formats including: UNC, Analyze, Dicom, NIFTI, Tiff, Jpeg, Gif, PNG ... imagej [options] image [ image2 ... image3 ] -h print help and more options -o open images in an open ImageJ panel -p <N> open images in ImageJ panel number <N> -x <MB> set available memory (default=2048 max=32023) Open other images in this ImageJ panel as follows: imagej -p 11 <image1> [<image2> ... <imageN>] ^\2020-09-04 12:28:26 Full thread dump OpenJDK 64-Bit Server VM (25.232-b09 mixed mode): "DICOM open" #272 prio=4 os_prio=0 tid=0x00007f294c154000 nid=0x14c054 in Object.wait() [0x00007f29ac932000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:264) - locked <0x00000000800a4318> (a java.awt.Component$AWTTreeLock) at java.awt.Dialog.show(Dialog.java:1084) at java.awt.Component.show(Component.java:1671) at java.awt.Component.setVisible(Component.java:1623) at java.awt.Window.setVisible(Window.java:1014) at java.awt.Dialog.setVisible(Dialog.java:1005) at ij.gui.GenericDialog.showDialog(GenericDialog.java:1381) at DICOM_open.run(DICOM_open.java:80) at ij.IJ.runUserPlugIn(IJ.java:240) at ij.IJ.runUserPlugIn(IJ.java:255) at ij.IJ.runPlugIn(IJ.java:203) at ij.Executer.runCommand(Executer.java:150) at ij.Executer.run(Executer.java:68) at java.lang.Thread.run(Thread.java:748) "Close" #270 prio=4 os_prio=0 tid=0x00007f294c121800 nid=0x14c027 in Object.wait() [0x00007f29adb44000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at java.awt.EventQueue.invokeAndWait(EventQueue.java:1343) - locked <0x00000000e2936900> (a java.awt.EventQueue$1AWTInvocationLock) at java.awt.Window.doDispose(Window.java:1210) at java.awt.Window.dispose(Window.java:1147) at ij.gui.ImageWindow.close(ImageWindow.java:444) at ij.gui.StackWindow.close(StackWindow.java:204) at ij.ImagePlus.close(ImagePlus.java:447) at ij.plugin.Commands.closeImage(Commands.java:138) at ij.plugin.Commands.close(Commands.java:83) at ij.plugin.Commands.run(Commands.java:29) at ij.IJ.runPlugIn(IJ.java:209) at ij.Executer.runCommand(Executer.java:150) at ij.Executer.run(Executer.java:68) at java.lang.Thread.run(Thread.java:748) "TimerQueue" #24 daemon prio=5 os_prio=0 tid=0x00007f294c170000 nid=0x14bebd waiting on condition [0x00007f29ad53b000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000000801b2368> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) at java.util.concurrent.DelayQueue.take(DelayQueue.java:211) at javax.swing.TimerQueue.run(TimerQueue.java:174) at java.lang.Thread.run(Thread.java:748) "DestroyJavaVM" #20 prio=5 os_prio=0 tid=0x00007f29e804c800 nid=0x14be83 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Run$_AWT-EventQueue-0" #17 prio=6 os_prio=0 tid=0x00007f29e8527000 nid=0x14be9e waiting on condition [0x00007f29ae038000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000000801d2088> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) at java.awt.EventQueue.getNextEvent(EventQueue.java:554) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:187) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:109) at java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:190) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758) at java.awt.EventQueue.access$500(EventQueue.java:97) at java.awt.EventQueue$3.run(EventQueue.java:709) at java.awt.EventQueue$3.run(EventQueue.java:703) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74) at java.awt.EventQueue.dispatchEvent(EventQueue.java:728) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) "AWT-Shutdown" #18 prio=5 os_prio=0 tid=0x00007f29e8525800 nid=0x14be9d in Object.wait() [0x00007f29ae13a000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:295) - locked <0x00000000801d9e78> (a java.lang.Object) at java.lang.Thread.run(Thread.java:748) "AWT-XAWT" #16 daemon prio=6 os_prio=0 tid=0x00007f29e8428800 nid=0x14be9c runnable [0x00007f29ae43b000] java.lang.Thread.State: RUNNABLE at sun.awt.X11.XToolkit.waitForEvents(Native Method) at sun.awt.X11.XToolkit.run(XToolkit.java:574) at sun.awt.X11.XToolkit.run(XToolkit.java:538) at java.lang.Thread.run(Thread.java:748) "Java2D Disposer" #14 daemon prio=10 os_prio=0 tid=0x00007f29e83fc000 nid=0x14be9b in Object.wait() [0x00007f29ae53c000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144) - locked <0x00000000801d2310> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165) at sun.java2d.Disposer.run(Disposer.java:148) at java.lang.Thread.run(Thread.java:748) "GC Daemon" #13 daemon prio=2 os_prio=0 tid=0x00007f29e83ae000 nid=0x14be9a in Object.wait() [0x00007f29c020e000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000080001c78> (a sun.misc.GC$LatencyLock) at sun.misc.GC$Daemon.run(GC.java:117) - locked <0x0000000080001c78> (a sun.misc.GC$LatencyLock) "RMI Reaper" #12 prio=5 os_prio=0 tid=0x00007f29e83a8800 nid=0x14be99 in Object.wait() [0x00007f29c030f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000080008698> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144) - locked <0x0000000080008698> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165) at sun.rmi.transport.ObjectTable$Reaper.run(ObjectTable.java:351) at java.lang.Thread.run(Thread.java:748) "RMI TCP Accept-0" #11 daemon prio=5 os_prio=0 tid=0x00007f29e83a4000 nid=0x14be98 runnable [0x00007f29c0410000] java.lang.Thread.State: RUNNABLE at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409) at java.net.ServerSocket.implAccept(ServerSocket.java:560) at java.net.ServerSocket.accept(ServerSocket.java:528) at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:405) at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:377) at java.lang.Thread.run(Thread.java:748) "Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007f29e8143800 nid=0x14be96 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007f29e8130800 nid=0x14be95 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f29e812e800 nid=0x14be94 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f29e812c800 nid=0x14be93 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f29e811d800 nid=0x14be92 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f29e811b800 nid=0x14be91 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f29e80f1000 nid=0x14be90 in Object.wait() [0x00007f29c0fd3000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144) - locked <0x0000000080018348> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216) "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f29e80ec800 nid=0x14be8f in Object.wait() [0x00007f29c10d4000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x0000000080010b18> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) "VM Thread" os_prio=0 tid=0x00007f29e80e2800 nid=0x14be8e runnable "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f29e805f800 nid=0x14be84 runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f29e8061800 nid=0x14be85 runnable "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f29e8063000 nid=0x14be86 runnable "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f29e8065000 nid=0x14be87 runnable "GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007f29e8066800 nid=0x14be88 runnable "GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007f29e8068800 nid=0x14be89 runnable "GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007f29e806a000 nid=0x14be8a runnable "GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007f29e806c000 nid=0x14be8b runnable "GC task thread#8 (ParallelGC)" os_prio=0 tid=0x00007f29e806d800 nid=0x14be8c runnable "GC task thread#9 (ParallelGC)" os_prio=0 tid=0x00007f29e806f800 nid=0x14be8d runnable "VM Periodic Task Thread" os_prio=0 tid=0x00007f29e8150000 nid=0x14be97 waiting on condition JNI global references: 786 Heap PSYoungGen total 593408K, used 241815K [0x00000000d5580000, 0x00000000ffc80000, 0x0000000100000000) eden space 495104K, 46% used [0x00000000d5580000,0x00000000e35e5d10,0x00000000f3900000) from space 98304K, 12% used [0x00000000f3900000,0x00000000f44c0140,0x00000000f9900000) to space 95232K, 0% used [0x00000000f9f80000,0x00000000f9f80000,0x00000000ffc80000) ParOldGen total 324096K, used 153537K [0x0000000080000000, 0x0000000093c80000, 0x00000000d5580000) object space 324096K, 47% used [0x0000000080000000,0x00000000895f05a0,0x0000000093c80000) Metaspace used 23563K, capacity 23804K, committed 24240K, reserved 1071104K class space used 2370K, capacity 2463K, committed 2480K, reserved 1048576K -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hi Fred,
not a clear solution, but one of the threads causing the deadlock is related to closing an image. Please check your WindowListener! (1) Is it guaranteed that you call removeWindowListener before Diffusion_Multimodal exits? (Note that it does not hurt to call a 'remove' from a listener too often. It does hurt to call 'add' for a listener more than once, because then the listener will be entered more than once, get callbacks more than once, and must be removed more than once). (2) If Diffusion_Multimodal has ended and its windowClosed or WindowClosing method would get called, could it do something that (i) makes it hang or (ii) leads to something being called on the EventQueue or something that modifies the screen? (3) If you use any swing calls (jvax.swing, not AWT), note that swing is not thread-safe. Typically, you should call swing functions only via SwingUtilities.invokeLater. Michael ________________________________________________________________ On 04.09.20 21:33, Fred Damen wrote: > Greetings, > > I am able to consitently get imagej to lock up, and I am a loss at what I > am directly or indirectly doing to cause this. The scenario is: > my plugin DICOM_open creates a GenericDialog with an addDialogListener, > which displays and after showDialog returns opens a set of DICOM files as > a hyperstack. After this I run another plugin, Diffusion_Multimodal, > which creates a GenericDialog and after the showDialog processes this > hyperstack creating a set of images in windows; these windows have > listeners - method that add and removes listener is below. Closing the > hyperstack and running DICOM_open again causes imagej to lockup within > showDialog, see first entry in thread stack traces. > > I can run DICOM_open only, over and over again, without any lockup. I can > run Diffusion_Multimodal, after the first DICOM_open, over and over again > without any lockup. Although, running DICOM_open after > Diffusion_Multimodal lockups everytime. I have run this code lots and > lots in the past and do not remember this scenario ever happening. > > I discovered this on release 1.52u14 and confirmed it still happens on > 1.53e14. Any insites and / or suggestion on how to debug this would be > greatly appriciated. > > Thanks in advance, > > Fred -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Greetings Michael,
Questions (asked out of ignorance / not as a challenge) inline... Thanks, Fred On Mon, September 7, 2020 7:25 am, Michael Schmid wrote: > Hi Fred, > > not a clear solution, but one of the threads causing the deadlock is > related to closing an image. Please check your WindowListener! 1) How, using the stack traces, to correlate the "Close" thread with the "DICOM_open" thread? I assume the subject resource of each of their locks is identified by the number in <>, and they are different. 2) Logically why would a GenericDialog care, or even know, about a WindowListener of a image window?, i.e., the WindowListeners are object specific and as such they are only called for the window they were register against, i.e, not like ImageListeners. At the point of lockup there are no other windows, besides the main window, opened. 2.1) Multiple WindowListeners should be allowed and called independent of thread safety; where the lockup only comes to play when more than one thread tries to lock the same resource. > > (1) Is it guaranteed that you call removeWindowListener before > Diffusion_Multimodal exits? 3) "Diffusion_Multimodal exits" is a little nebulous. The run method that was called when Diffusion_Multimodal was run as a plugin has returned. At this point the WindowListeners for the source or results windows have not been removed. When one of the results windows are closed, the WindowListeners (all listeners) are removed for all the results and source windows. 3.1) I have included the source code that preforms this, in case someone can spot something I missed, n.b., dimp is the same as imp. 3.2) I have added this after removing the window listener: for(WindowListener wl : dimp.getWindow().getWindowListeners()) IJ.log("WindowListeners: "+wl); and it produced this: WindowListeners: Trace - Untitled WindowListeners: sun.awt.im.InputMethodContext@5e0e286e I assume the first is imagej's (as that is the window title) and the other is Java's WindowListener. > (Note that it does not hurt to call a 'remove' from a listener too > often. It does hurt to call 'add' for a listener more than once, because > then the listener will be entered more than once, get callbacks more > than once, and must be removed more than once). 4) I assume that once the Window is closed, all the WindowListeners registered for this Window are removed. > (2) If Diffusion_Multimodal has ended and its windowClosed or > WindowClosing method would get called, could it do something that (i) > makes it hang or (ii) leads to something being called on the EventQueue > or something that modifies the screen? 5) Not that I can tell. The only thing the WindowListener does is close all the results windows. The Mouse and Key listeners cause a plot of the currently selected voxel. In the testing I did for the posting of this issue there is no key or mouse action going on. 6) Why would this effect the GenericDialog in the DICOM_open plugin? > (3) If you use any swing calls (jvax.swing, not AWT), note that swing is > not thread-safe. Typically, you should call swing functions only via > SwingUtilities.invokeLater. 7) The only GUI stuff I used in these two plugin(s) is GenericDialog. I included the GenericDialog usage code from DICOM_open. > > > Michael > ________________________________________________________________ > On 04.09.20 21:33, Fred Damen wrote: >> Greetings, >> >> I am able to consitently get imagej to lock up, and I am a loss at what >> I >> am directly or indirectly doing to cause this. The scenario is: >> my plugin DICOM_open creates a GenericDialog with an addDialogListener, >> which displays and after showDialog returns opens a set of DICOM files >> as >> a hyperstack. After this I run another plugin, Diffusion_Multimodal, >> which creates a GenericDialog and after the showDialog processes this >> hyperstack creating a set of images in windows; these windows have >> listeners - method that add and removes listener is below. Closing the >> hyperstack and running DICOM_open again causes imagej to lockup within >> showDialog, see first entry in thread stack traces. >> >> I can run DICOM_open only, over and over again, without any lockup. I >> can >> run Diffusion_Multimodal, after the first DICOM_open, over and over >> again >> without any lockup. Although, running DICOM_open after >> Diffusion_Multimodal lockups everytime. I have run this code lots and >> lots in the past and do not remember this scenario ever happening. >> >> I discovered this on release 1.52u14 and confirmed it still happens on >> 1.53e14. Any insites and / or suggestion on how to debug this would be >> greatly appriciated. >> >> Thanks in advance, >> >> Fred > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hi Fred,
trying to answer some of your questions: > 1) How, using the stack traces, to correlate the "Close" thread > with the "DICOM_open" thread? I assume the subject resource of > each of their locks is identified by the number in <>, and they > are different. Among the threads in a "WAITING (on object monitor)" state, one of them is trying to show the GenericDialog, and I guess that this is your problem. The other suspicious one is "Close" ij.gui.ImageWindow.close, calling java.awt.Window.dispose because I would guess that closing an image should be fast and finished by then. Looking at it again, I am not so sure. A real deadlock is usually marked by "BLOCKED (on object monitor)" and I agree that then the numbers in <> should appear twice. So it To me, the only other suspicious thing is the "RMI Reaper" #12 related to a sun.rmi.transport.ObjectTable - a class that I have not idea about. > Logically why would a GenericDialog care, or even know, about a > WindowListener of a image window? I think that adding and removing windows contains operations that have to be done in *one* queue (one thread, e.g., the EventQueue). So, if closing one image is not finished it can happen that you can't open another window. Your stack trace shows that the 'dispose' of the StackWindow is in the EventQueue.invokeAndWait: it looks like is blocked because something else happens on the EventQueue (but strange enough the EventQueue seems to be idle [parking]). > Multiple WindowListeners should be allowed Yes, they are allowed. Just call removeWindowListener for each time you call addWindowListener, especially if your windowClosing or WindowClosed callback could do some action that might not be appropriate at a later time. > 3) "Diffusion_Multimodal exits" is a little nebulous. What I wanted to say: When everything that you plugin is supposed to do has finished and there is not need for it being a WindowListener, call removeWindowListener (preferably before any other cleanup operations, especially if they might cause WindowListener callbacks) > 4) I assume that once the Window is closed, all the WindowListeners > registered for this Window are removed. Closing has two parts: (i) "setVisible(false)" has only the effect it says, you can call "setVisible(true)" and the window will be back again. (ii) "dispose()" is a bit stronger, but one can still make the window displayable with pack() or show() as long as a reference to it exists. I am not sure whether whether dispose() de-registers the windowListeners; but I fear it doesn't. You may try. Anyhow, looking at your stack trace again: I see now "windowClosing" or "windowClosed", so if the problem is related to the WindowListener it would have to be code that is executed by a WindowListener callback in a separate thread. > 5) ... The only thing the WindowListener does is close > all the results windows. My feeling is that it is not a good idea to close windows in a windowClosing() or windowClosed() method (I can't give a clear reason why). You may try to put this into a separate thread, maybe with EventQueue.invokeLater, and maybe also add debug messages to see what actually happens. But maybe it is also the sun.rmi.transport.ObjectTable issue, in case closing the results windows somehow calls this class? In case it is a bug in Java - do you have Oracle or OpenJDK? (and which version?) If you have both Oracle and JDK installed, maybe try the other one, to see whether it could be a java bug. So far a few more thoughts... Michael ________________________________________________________________ On 07.09.20 21:51, Fred Damen wrote: > Greetings Michael, > > Questions (asked out of ignorance / not as a challenge) inline... > > Thanks, > > Fred > > On Mon, September 7, 2020 7:25 am, Michael Schmid wrote: >> Hi Fred, >> >> not a clear solution, but one of the threads causing the deadlock is >> related to closing an image. Please check your WindowListener! > 1) How, using the stack traces, to correlate the "Close" thread with the > "DICOM_open" thread? I assume the subject resource of each of their locks > is identified by the number in <>, and they are different. > 2) Logically why would a GenericDialog care, or even know, about a > WindowListener of a image window?, i.e., the WindowListeners are object > specific and as such they are only called for the window they were > register against, i.e, not like ImageListeners. At the point of lockup > there are no other windows, besides the main window, opened. > 2.1) Multiple WindowListeners should be allowed and called independent of > thread safety; where the lockup only comes to play when more than one > thread tries to lock the same resource. > >> >> (1) Is it guaranteed that you call removeWindowListener before >> Diffusion_Multimodal exits? > 3) "Diffusion_Multimodal exits" is a little nebulous. The run method that > was called when Diffusion_Multimodal was run as a plugin has returned. At > this point the WindowListeners for the source or results windows have not > been removed. When one of the results windows are closed, the > WindowListeners (all listeners) are removed for all the results and source > windows. > 3.1) I have included the source code that preforms this, in case someone > can spot something I missed, n.b., dimp is the same as imp. > 3.2) I have added this after removing the window listener: > for(WindowListener wl : dimp.getWindow().getWindowListeners()) > IJ.log("WindowListeners: "+wl); > and it produced this: > WindowListeners: Trace - Untitled > WindowListeners: sun.awt.im.InputMethodContext@5e0e286e > I assume the first is imagej's (as that is the window title) and the other > is Java's WindowListener. > >> (Note that it does not hurt to call a 'remove' from a listener too >> often. It does hurt to call 'add' for a listener more than once, because >> then the listener will be entered more than once, get callbacks more >> than once, and must be removed more than once). > 4) I assume that once the Window is closed, all the WindowListeners > registered for this Window are removed. > >> (2) If Diffusion_Multimodal has ended and its windowClosed or >> WindowClosing method would get called, could it do something that (i) >> makes it hang or (ii) leads to something being called on the EventQueue >> or something that modifies the screen? > 5) Not that I can tell. The only thing the WindowListener does is close > all the results windows. The Mouse and Key listeners cause a plot of the > currently selected voxel. In the testing I did for the posting of this > issue there is no key or mouse action going on. > 6) Why would this effect the GenericDialog in the DICOM_open plugin? > >> (3) If you use any swing calls (jvax.swing, not AWT), note that swing is >> not thread-safe. Typically, you should call swing functions only via >> SwingUtilities.invokeLater. > 7) The only GUI stuff I used in these two plugin(s) is GenericDialog. I > included the GenericDialog usage code from DICOM_open. > >> >> >> Michael >> ________________________________________________________________ >> On 04.09.20 21:33, Fred Damen wrote: >>> Greetings, >>> >>> I am able to consitently get imagej to lock up, and I am a loss at what >>> I >>> am directly or indirectly doing to cause this. The scenario is: >>> my plugin DICOM_open creates a GenericDialog with an addDialogListener, >>> which displays and after showDialog returns opens a set of DICOM files >>> as >>> a hyperstack. After this I run another plugin, Diffusion_Multimodal, >>> which creates a GenericDialog and after the showDialog processes this >>> hyperstack creating a set of images in windows; these windows have >>> listeners - method that add and removes listener is below. Closing the >>> hyperstack and running DICOM_open again causes imagej to lockup within >>> showDialog, see first entry in thread stack traces. >>> >>> I can run DICOM_open only, over and over again, without any lockup. I >>> can >>> run Diffusion_Multimodal, after the first DICOM_open, over and over >>> again >>> without any lockup. Although, running DICOM_open after >>> Diffusion_Multimodal lockups everytime. I have run this code lots and >>> lots in the past and do not remember this scenario ever happening. >>> >>> I discovered this on release 1.52u14 and confirmed it still happens on >>> 1.53e14. Any insites and / or suggestion on how to debug this would be >>> greatly appriciated. >>> >>> Thanks in advance, >>> >>> Fred >> >> -- >> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >> > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Greetings Michael,
thanks for the info... I now suspect that the "Close" thread had/has nothing to do with the subsequent lockup. I ran DICOM_open, Diffusion_Multimodal, no window closing, DICOM_open and it still locks up. The impetus of the "Close" thread was calling close within the windowClosed listener on the ImageWindow that was closed through the GUI; this has been rectified and the lockup still happens. Grasping at straws here: Diffusion_Multimodal uses a genericDialog of its own and calls F_Project.compute which uses Thread(s) and AtomicInteger. Since I can run Diffusion_Multimodal over and over again without any issues, I find it perplexing that a GenericDialog in another subsequently run plugin, i.e., all user object instances are unique, are interacting and causing an imagej wide lockup. The only thing I see different about the DICOM_open::GenericDialog and the Diffusion_Multimodal::GenericDialog is the former uses a DialogListener and the later does not. On the computer I am working on, Java is OpenJDK. I am suspecting a Java bug. Either way, I would still have to change these plugins to avoid said bug. Note: I did not see this lockup issue more than a few months ago. Thanks for the help, Fred On Wed, September 9, 2020 8:23 am, Michael Schmid wrote: > Hi Fred, > > trying to answer some of your questions: > > > 1) How, using the stack traces, to correlate the "Close" thread > > with the "DICOM_open" thread? I assume the subject resource of > > each of their locks is identified by the number in <>, and they > > are different. > Among the threads in a "WAITING (on object monitor)" state, one of them > is trying to show the GenericDialog, and I guess that this is your > problem. > The other suspicious one is "Close" > ij.gui.ImageWindow.close, calling java.awt.Window.dispose > because I would guess that closing an image should be fast and finished > by then. > > Looking at it again, I am not so sure. A real deadlock is usually marked > by "BLOCKED (on object monitor)" and I agree that then the numbers in <> > should appear twice. So it > > To me, the only other suspicious thing is the "RMI Reaper" #12 related > to a sun.rmi.transport.ObjectTable - a class that I have not idea about. > > > > Logically why would a GenericDialog care, or even know, about a > > WindowListener of a image window? > I think that adding and removing windows contains operations that have > to be done in *one* queue (one thread, e.g., the EventQueue). So, if > closing one image is not finished it can happen that you can't open > another window. > Your stack trace shows that the 'dispose' of the StackWindow is in the > EventQueue.invokeAndWait: it looks like is blocked because something > else happens on the EventQueue (but strange enough the EventQueue seems > to be idle [parking]). > > > Multiple WindowListeners should be allowed > Yes, they are allowed. Just call removeWindowListener for each time you > call addWindowListener, especially if your windowClosing or WindowClosed > callback could do some action that might not be appropriate at a later > time. > > > 3) "Diffusion_Multimodal exits" is a little nebulous. > What I wanted to say: When everything that you plugin is supposed to do > has finished and there is not need for it being a WindowListener, call > removeWindowListener (preferably before any other cleanup operations, > especially if they might cause WindowListener callbacks) > > > 4) I assume that once the Window is closed, all the WindowListeners > > registered for this Window are removed. > Closing has two parts: > (i) "setVisible(false)" has only the effect it says, you can call > "setVisible(true)" and the window will be back again. > (ii) "dispose()" is a bit stronger, but one can still make the window > displayable with pack() or show() as long as a reference to it exists. > I am not sure whether whether dispose() de-registers the > windowListeners; but I fear it doesn't. You may try. > > Anyhow, looking at your stack trace again: I see now "windowClosing" or > "windowClosed", so if the problem is related to the WindowListener it > would have to be code that is executed by a WindowListener callback in a > separate thread. > > > 5) ... The only thing the WindowListener does is close > > all the results windows. > My feeling is that it is not a good idea to close windows in a > windowClosing() or windowClosed() method (I can't give a clear reason > why). You may try to put this into a separate thread, maybe with > EventQueue.invokeLater, and maybe also add debug messages to see what > actually happens. > But maybe it is also the sun.rmi.transport.ObjectTable issue, in case > closing the results windows somehow calls this class? > > In case it is a bug in Java - do you have Oracle or OpenJDK? (and which > version?) > If you have both Oracle and JDK installed, maybe try the other one, to > see whether it could be a java bug. > > > So far a few more thoughts... > > Michael > ________________________________________________________________ > On 07.09.20 21:51, Fred Damen wrote: > > Greetings Michael, > > > > Questions (asked out of ignorance / not as a challenge) inline... > > > > Thanks, > > > > Fred > > > > On Mon, September 7, 2020 7:25 am, Michael Schmid wrote: > >> Hi Fred, > >> > >> not a clear solution, but one of the threads causing the deadlock is > >> related to closing an image. Please check your WindowListener! > > 1) How, using the stack traces, to correlate the "Close" thread with > the > > "DICOM_open" thread? I assume the subject resource of each of their > locks > > is identified by the number in <>, and they are different. > > 2) Logically why would a GenericDialog care, or even know, about a > > WindowListener of a image window?, i.e., the WindowListeners are object > > specific and as such they are only called for the window they were > > register against, i.e, not like ImageListeners. At the point of lockup > > there are no other windows, besides the main window, opened. > > 2.1) Multiple WindowListeners should be allowed and called independent > of > > thread safety; where the lockup only comes to play when more than one > > thread tries to lock the same resource. > > > >> > >> (1) Is it guaranteed that you call removeWindowListener before > >> Diffusion_Multimodal exits? > > 3) "Diffusion_Multimodal exits" is a little nebulous. The run method > that > > was called when Diffusion_Multimodal was run as a plugin has returned. > At > > this point the WindowListeners for the source or results windows have > not > > been removed. When one of the results windows are closed, the > > WindowListeners (all listeners) are removed for all the results and > source > > windows. > > 3.1) I have included the source code that preforms this, in case > someone > > can spot something I missed, n.b., dimp is the same as imp. > > 3.2) I have added this after removing the window listener: > > for(WindowListener wl : > dimp.getWindow().getWindowListeners()) > > IJ.log("WindowListeners: "+wl); > > and it produced this: > > WindowListeners: Trace - Untitled > > WindowListeners: sun.awt.im.InputMethodContext@5e0e286e > > I assume the first is imagej's (as that is the window title) and the > other > > is Java's WindowListener. > > > >> (Note that it does not hurt to call a 'remove' from a listener too > >> often. It does hurt to call 'add' for a listener more than once, > because > >> then the listener will be entered more than once, get callbacks more > >> than once, and must be removed more than once). > > 4) I assume that once the Window is closed, all the WindowListeners > > registered for this Window are removed. > > > >> (2) If Diffusion_Multimodal has ended and its windowClosed or > >> WindowClosing method would get called, could it do something that (i) > >> makes it hang or (ii) leads to something being called on the > EventQueue > >> or something that modifies the screen? > > 5) Not that I can tell. The only thing the WindowListener does is > close > > all the results windows. The Mouse and Key listeners cause a plot of > the > > currently selected voxel. In the testing I did for the posting of this > > issue there is no key or mouse action going on. > > 6) Why would this effect the GenericDialog in the DICOM_open plugin? > > > >> (3) If you use any swing calls (jvax.swing, not AWT), note that swing > is > >> not thread-safe. Typically, you should call swing functions only via > >> SwingUtilities.invokeLater. > > 7) The only GUI stuff I used in these two plugin(s) is GenericDialog. > I > > included the GenericDialog usage code from DICOM_open. > > > >> > >> > >> Michael > >> ________________________________________________________________ > >> On 04.09.20 21:33, Fred Damen wrote: > >>> Greetings, > >>> > >>> I am able to consitently get imagej to lock up, and I am a loss at > what > >>> I > >>> am directly or indirectly doing to cause this. The scenario is: > >>> my plugin DICOM_open creates a GenericDialog with an > addDialogListener, > >>> which displays and after showDialog returns opens a set of DICOM > files > >>> as > >>> a hyperstack. After this I run another plugin, Diffusion_Multimodal, > >>> which creates a GenericDialog and after the showDialog processes this > >>> hyperstack creating a set of images in windows; these windows have > >>> listeners - method that add and removes listener is below. Closing > the > >>> hyperstack and running DICOM_open again causes imagej to lockup > within > >>> showDialog, see first entry in thread stack traces. > >>> > >>> I can run DICOM_open only, over and over again, without any lockup. > I > >>> can > >>> run Diffusion_Multimodal, after the first DICOM_open, over and over > >>> again > >>> without any lockup. Although, running DICOM_open after > >>> Diffusion_Multimodal lockups everytime. I have run this code lots > and > >>> lots in the past and do not remember this scenario ever happening. > >>> > >>> I discovered this on release 1.52u14 and confirmed it still happens > on > >>> 1.53e14. Any insites and / or suggestion on how to debug this would > be > >>> greatly appriciated. > >>> > >>> Thanks in advance, > >>> > >>> Fred > >> > >> -- > >> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > >> > > > > -- > > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hi,
Does anybody here use the IJ-Robot plugin on a mac? I am asking because somebody contacted me that it does not seem to work in Catalina but I do not have a mac to try it. Apparently the code below does not do anything (but it does in my linux install: moves the mouse to the coordinates 100, 300 of the screen). showMessage("IJ_Robot Demo","Please do not move the mouse after pressing OK"); wait(1000); // wait 1 sec. before starting run("IJ Robot", "order=Move x_point=100 y_point=300"); Thanks Gabriel -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Free forum by Nabble | Edit this page |