GenericDialog and imagej lockups

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

GenericDialog and imagej lockups

Fred Damen
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
Reply | Threaded
Open this post in threaded view
|

Re: GenericDialog and imagej lockups

Michael Schmid
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
Reply | Threaded
Open this post in threaded view
|

Re: GenericDialog and imagej lockups

Fred Damen
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
Reply | Threaded
Open this post in threaded view
|

Re: GenericDialog and imagej lockups

Michael Schmid
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
Reply | Threaded
Open this post in threaded view
|

Re: GenericDialog and imagej lockups

Fred Damen
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
Reply | Threaded
Open this post in threaded view
|

IJ-Robot issues in macOS?

Gabriel Landini
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