bigdataviewer / bigdataviewer-core

ImgLib2-based viewer for registered SPIM stacks and more
BSD 2-Clause "Simplified" License
33 stars 35 forks source link

Deadlock related to SynchronizedViewerState #147

Open tpietzsch opened 1 year ago

tpietzsch commented 1 year ago

@tischi reported a dead-lock issue on gitter.

The dead-lock happens when accessing SynchronizedViewerState.sourceOrder() method from a synchronized block in MultiResolutionRenderer. At the same time, SynchronizedViewerState.setViewerTransform() tries to MultiResolutionRenderer.requestRepaint (which is synchronized) form a synchronized block.

It is surprising that this has not blown up somewhere else yet, because there are other uses of SynchronizedViewerState methods in synchronized blocks of MultiResolutionRenderer.

Found one Java-level deadlock:
=============================
"PainterThread":
  waiting to lock monitor 0x00007fa1f27e71e8 (object 0x00000006c15bc660, a bdv.viewer.SynchronizedViewerState),
  which is held by "AWT-EventQueue-0"
"AWT-EventQueue-0":
  waiting to lock monitor 0x00007fa1f15ae0e8 (object 0x00000006c2049fa8, a bdv.viewer.render.MultiResolutionRenderer),
  which is held by "PainterThread"

Java stack information for the threads listed above:
===================================================
"PainterThread":
        at bdv.viewer.SynchronizedViewerState.sourceOrder(SynchronizedViewerState.java:589)
        - waiting to lock <0x00000006c15bc660> (a bdv.viewer.SynchronizedViewerState)
        at org.embl.mobie.viewer.bdv.render.AccumulateAlphaBlendingProjectorARGB.getOrder(AccumulateAlphaBlendingProjectorARGB.java:80)
        - locked <0x00000006c1f0de90> (a java.lang.Class for org.embl.mobie.viewer.bdv.render.AccumulateAlphaBlendingProjectorARGB)
        at org.embl.mobie.viewer.bdv.render.AccumulateAlphaBlendingProjectorARGB.<init>(AccumulateAlphaBlendingProjectorARGB.java:71)
        at org.embl.mobie.viewer.bdv.render.AccumulateAlphaBlendingProjectorARGBFactory.createProjector(AccumulateAlphaBlendingProjectorARGBFactory.java:55)
        at bdv.viewer.render.ProjectorFactory.createProjector(ProjectorFactory.java:191)
        at bdv.viewer.render.MultiResolutionRenderer.createProjector(MultiResolutionRenderer.java:668)
        at bdv.viewer.render.MultiResolutionRenderer.paintFullFrame(MultiResolutionRenderer.java:478)
        - locked <0x00000006c2049fa8> (a bdv.viewer.render.MultiResolutionRenderer)
        at bdv.viewer.render.MultiResolutionRenderer.paint(MultiResolutionRenderer.java:452)
        at bdv.viewer.ViewerPanel.paint(ViewerPanel.java:464)
        at bdv.viewer.render.PainterThread.run(PainterThread.java:82)
"AWT-EventQueue-0":
        at bdv.viewer.render.MultiResolutionRenderer.requestRepaint(MultiResolutionRenderer.java:339)
        - waiting to lock <0x00000006c2049fa8> (a bdv.viewer.render.MultiResolutionRenderer)
        at bdv.viewer.ViewerPanel.requestRepaint(ViewerPanel.java:488)
        at bdv.viewer.ViewerPanel.viewerStateChanged(ViewerPanel.java:622)
        at bdv.viewer.BasicViewerState.lambda$notifyListeners$3(BasicViewerState.java:1650)
        at bdv.viewer.BasicViewerState$$Lambda$267/1019831085.accept(Unknown Source)
        at java.util.ArrayList.forEach(ArrayList.java:1259)
        at bdv.viewer.BasicViewerState.notifyListeners(BasicViewerState.java:1650)
        at bdv.viewer.BasicViewerState.setViewerTransform(BasicViewerState.java:353)
        at bdv.viewer.SynchronizedViewerState.setViewerTransform(SynchronizedViewerState.java:170)
tpietzsch commented 1 year ago

To solve this, the best approach is probably to try and make MultiResolutionRenderer.requestRepaint not synchronized.